You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vapor 4认证异常:用户已登录仍提示未认证

解决Vapor中OAuth2登录后无法访问受保护端点的问题

问题场景

我有一个采用OAuth 2.0作为认证机制的iOS客户端,以Google登录为例完成认证流程,但用户登录后无法访问配置了认证校验的端点,提示未认证。

相关代码与配置

登录处理代码

func processGoogleLogin(request: Request, token: String) throws -> EventLoopFuture<ResponseEncodable> {
    try Google
        .getUser(on: request)
        .flatMap { userInfo in
            User
                .query(on: request.db)
                .filter(\.$email == userInfo.email)
                .first()
                .flatMap { foundUser in
                    guard let existingUser = foundUser else {
                        // 创建新用户
                        return user
                            .save(on: request.db)
                            .map {
                                request.session.authenticate(user)
                                // 携带信息重定向
                            }
                    }
                    request.session.authenticate(existingUser)
                    // 携带信息重定向
                }
        }
}

错误信息

{
"error": true,
"reason": "User not authenticated."
}

认证相关配置

  • User模型已遵循ModelSessionAuthenticatable协议
  • Session中间件配置:
let imperialController = ImperialController(sessionsMiddleware: app.sessions.middleware)
app.middleware.use(app.sessions.middleware)
  • ImperialController代码:
class ImperialController {
    private let sessionsMiddleware: Middleware
    
    init(sessionsMiddleware: Middleware) {
        self.sessionsMiddleware = sessionsMiddleware
    }
    ....
}
  • 受保护路由配置:
let protected = app.grouped(User.guardMiddleware())

protected.get { req -> HTTPResponseStatus in
    return .ok
}

解决步骤

  • 调整Session中间件顺序:确保app.sessions.middleware在所有路由处理中间件之前添加,必须早于User.guardMiddleware()。如果中间件顺序颠倒,会导致还没解析Session就执行认证校验,直接判定未认证。
  • 确认新用户实例的有效性:创建新用户的分支里,request.session.authenticate(user)中的user必须是刚完成保存、带有有效ID的实例——ModelSessionAuthenticatable依赖模型ID存储会话,未持久化的实例无法正常写入Session。
  • 检查Session存储配置:验证Vapor的Session存储是否正确初始化(比如内存存储、Redis等),存储未配置的话,会话无法持久化,后续请求读取不到认证信息。
  • 补充Session认证中间件:受保护路由组需要同时添加User.sessionAuthenticator()和User.guardMiddleware(),前者负责从Session中解析用户,后者负责校验用户是否已认证。修改路由配置:
let protected = app.grouped(User.sessionAuthenticator(), User.guardMiddleware())

protected.get { req -> HTTPResponseStatus in
    return .ok
}
  • 校验重定向的Cookie携带:登录后的重定向响应必须包含正确的Set-Cookie头,同时确认iOS客户端会在后续请求中携带该Cookie。
  • 调试Session内容:在登录成功后和受保护端点请求时,打印Session数据和认证状态,确认会话中是否存在正确的用户标识。比如在登录逻辑的map闭包中添加:
print(request.session.data)

在受保护端点内添加:

print(request.session.data)
print(req.auth.has(User.self))

内容的提问来源于stack exchange,提问作者Nathace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:39:22