我有两个 Node.js 服务器应用程序。第一个在 localhost:8081 上运行 Koa.JS,而第二个在 localhost:8080 上运行 Vue.JS。在两个服务器中,我使用的是 HTTP 而不是 HTTPS。
Koa.JS 服务器使用 Passport.JS 执行 oAuth2 登录流程,并提供端点以从 API 获取数据并将承载令牌传递给授权标头。
Vue.js 服务器负责客户端代码。它使用 axios 库调用 Koa 端点。
如果我打开浏览器,并针对 Koa 服务器测试登录流程,一切都很好并且工作正常。以下是步骤:
本地主机: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 端点 localhost:8081/api/oauth/authenticate 来执行登录
- 登录并授予访问权限
- 在 Koa 上 /callback 重定向回 localhost:8080/auth?isUserLoggedIn=true
在 Vue 应用程序中,使用 this.$route.query.isUserLoggedIn 检索查询参数,如果为 true,则调用 Koa 端点以获取用户配置文件数据 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。
经过进一步调查,具有配置文件端点的 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 调用此端点时,它才会由于 ctx.sesssion 为空而失败。
知道是什么将 ctx.session 重置为 null 吗?