我有两个Node.js服务器应用程序 . 第一个在localhost:8081上运行Koa.JS,而第二个在localhost:8080上运行Vue.JS . 在两个服务器中,我使用HTTP而不是HTTPS .
Koa.JS服务器使用Passport.JS执行oAuth2登录流程,并提供 endpoints 以从API获取数据并将承载令牌传递给Authorization标头 .
Vue.js服务器负责客户端代码 . 它使用axios库调用Koa endpoints .
如果我打开浏览器,并针对Koa服务器测试登录流程,那么一切正常并正常工作 . 以下是步骤:
- localhost:8081 / api / oauth / authenticate
router.get(
'/authenticate',
passport.authenticate(
'oauth2',
{ scope: config.scope }
))
-
用户登录并授予访问权限
-
完成后,回调称为localhost:8081 / api / oauth / callback
router.get(
'/callback',
ctx => {
return passport.authenticate(
'oauth2',
async (err, user) => {
if (err) ctx.throw(err)
const tokenSession = new token(ctx.session)
await ctx.login(user)
tokenSession.setPublicCredentials(user)
ctx.redirect(`${config.vuehost}/auth?isUserLoggedIn=true`)
})(ctx)
})
-
会话与用户信息一起保存
-
用户打开新选项卡转到localhost:8081 / api / user / profile
router.get(
'/user/profile',
async (ctx) => {
if (ctx.isAuthenticated) {
const options = {
headers: { Authorization: `Bearer ${ctx.session.passport.user.access_token}` },
json: true,
method: 'GET',
uri: 'https://developer.mycoolapi.com/userprofile/v1/users/@me'
}
const response = await rp(options)
ctx.body = JSON.stringify(response)
} else {
ctx.throw(401)
}
}
)
- Koa服务器调用其他API来检索用户配置文件数据,Vue.js应用程序获取正确的JSON响应
但是,如果我执行以下操作,ctx.session会丢失:
-
导航到localhost:8080(Vue.js服务器)
-
通过重定向到Koa endpoints localhost:8081 / api / oauth / authenticate来执行登录
-
登录并授予访问权限
-
On Koa / callback重定向回localhost:8080 / auth?isUserLoggedIn = true
-
在Vue应用程序中,使用此命令检索查询参数 . $ route.query.isUserLoggedIn,如果为true,则调用Koa endpoints 以获取用户配置文件数据localhost:8081 / api / user / profile
axios.get('http://localhost:8081/api/user/profile')
.then (response => {
console.info(`\nsetUserData response: ${JSON.stringify(response)}\n`)
})
.catch (err => {
console.info(`\nsetUserData error: ${JSON.stringify(err)}\n`)
})
最后一步返回401 Unauthorized .
经过进一步调查,具有配置文件 endpoints 的Koa路由位于appRoutes中间件中 . 这个中间件就在app.use(requireLogin)中间件之后,它检查会话是否经过身份验证(ctx.isAuthenticated()) .
'use strict'
const requireLogin = async (ctx, next) => {
if (ctx.isAuthenticated()) {
await next()
} else {
ctx.status = 401
ctx.body = {
errors: [{ title: 'Login required', status: 401 }]
}
}
}
module.exports = requireLogin
这是发生401错误的地方,因为此时ctx会话为空 .
// Add routing
app.use(authRoutes.routes())
app.use(authRoutes.allowedMethods())
app.use(requireLogin)
app.use(appRoutes.routes())
app.use(appRoutes.allowedMethods())
我是否正在处理某种时间问题?我尝试在我的Koa server.js文件中评论头盔中间件,但这没有帮助 .
请注意,如果我在同一个浏览器会话中打开一个新选项卡并转到localhost:8081 / api / user / profile,它可以正常工作 . 只有当从Vue.js调用此 endpoints 时才会因ctx.sesssion为空而失败 .
有什么想法将ctx.session重置为null?
1 回答
仔细阅读本文后:https://medium.com/@xgwang/a-practical-guide-to-cors-51e8fd329a1f,我终于能够解决问题了 .
在server.js中,将{credentials:true}传递给cors选项 .
在Vue.js中,将axios默认设置为:
最后,当使用axios从Vue.js调用Koa endpoints 时,传递给头文件{'Access-Control-Allow-Credentials':true}