使用 JWT 和 auth 中间件从'/user/login'重定向到'/user/me'

Posted

技术标签:

【中文标题】使用 JWT 和 auth 中间件从\'/user/login\'重定向到\'/user/me\'【英文标题】:Redirect from '/user/login' to '/user/me' in express with JWT and auth middleware使用 JWT 和 auth 中间件从'/user/login'重定向到'/user/me' 【发布时间】:2021-11-07 13:42:35 【问题描述】:

我试图在用户登录后将他们重定向到他们的个人资料。我想做的是当他们登录时,我们将通过凭据找到用户,然后从他们那里生成和验证令牌(注意 I为测试目的创建了一个用户 const)。两者都完成后,我将设置一个标头 Authorization,使用令牌,并将其传递给 /user/me 路由。这是我的路线:

(登录 POST 路由,“/user/login”):

router.post('/user/login', async (req, res) => 
    try 
        const user = await User.findByCredentials(req.body.email, req.body.password)
        const token = await user.generateAuthToken()
        
        res.header('Authorization', 'Bearer '+token)
        res.status(302).redirect('/user/me')
     catch (err) 
        res.status(400).send(err)
    
)

(个人资料路径:“/user/me”):

router.get('/user/me', auth, async (req, res) => 
    res.send(req.user)
)

(我在上一个方法中传递的“auth”中间件):

const auth = async (req, res, next) => 
    try
        const token = req.header('Authorization').replace('Bearer ', '')
        const decoded = jwt.verify(token, SECRET_TOKEN)
        const user = await User.findOne( _id: decoded._id, 'tokens.token': token)
        console.log(token)

        if(!user) 
            throw new Error("User not found")
        

        req.token = token
        req.user = user
        next()

     catch(err) 
        res.status(503).send(error: 'Please authenticate')
    

但是每当我尝试这个时,它都会从 auth 方法中给出我的 503 错误


   "error": "Please authenticate"

正如我在开发工具中看到的那样,授权标头正确传递。

如需更多信息,generateAuthTokenfindByCredentials 方法如下所示:

userSchema.methods.generateAuthToken = async function() 
    const user = this

    const token = jwt.sign( _id: user._id.toString() , SECRET_TOKEN)

    user.tokens = user.tokens.concat(token)

    await user.save()

    return token


userSchema.statics.findByCredentials = async (email, password) => 
    const user = await User.findOne(email)
    if(!user) 
        throw new Error(message: "Unable to log in.")
    

    const isValid = await bcrypt.compare(password, user.password)

    if(!isValid) 
        throw new Error(message: "Unable to log in.")
    

    return user

如需更多信息,我的用户模型如下所示:

const userSchema = mongoose.Schema(
    email:
        type: String,
        required: true,
        unique: true,
        trim: true,
        validate(value) 
            if(!validator.isEmail(value)) 
                throw new Error("Not a valid email")
            
         
    ,
    password:
        type: String,
        required: true,
        validate(value) 
            if(value === "password") 
                throw new Error("Enter a strong password.")
            

            if(value.length < 8) 
                throw new Error("Enter minimum 8 letters for a password.")
            
         
    ,
    tokens: [
        token:
            type: String,
            required: true
        
    ]
)

【问题讨论】:

“但是每当我尝试这个时,它都会从 auth 方法中给出我的 503 错误:” - 你无条件地发送 503。您的代码中还有其他可能失败的地方,所有这些都会导致 503。当您输出错误本身时,您会看到什么? @Tomalak 我的错误,它说“无法读取未定义的属性'替换'”。这意味着“授权”标头未定义。如何将它从 /user/login 传递给 /user/me? @Tomalak 我使用 cookie 解决了它。它现在工作正常。非常感谢!!! 【参考方案1】:

我已经通过使用 cookie 解决了这个问题。这可能是一种临时解决方法,但我会找到资源以使其更安全!

在登录路径中:

res.cookie('Authorization', `Bearer $token`, 
        maxAge: 60000,
)

在身份验证中间件中

const token = req.cookies['Authorization'].replace('Bearer ', '')

【讨论】:

您应该为每个请求设置授权标头。使用 cookie 只能回避问题,因为浏览器会为您管理 cookie 标头。使用 cookie 并不是解决此问题的最佳方法。探究如何在客户端一致地设置 Authorization 标头的问题。 好吧,重写您的服务器代码,以便根据情况发送正确的响应代码。 503 并不意味着“请验证”,它意味着“服务不可用”(即“服务器关闭”等)。 “未授权”是 401。像 "Cannot read property 'replace' of undefined" 这样的编程错误应该会导致 500。 非常感谢您的建议@Tomalak。我目前正在调查您提出的所有建议。

以上是关于使用 JWT 和 auth 中间件从'/user/login'重定向到'/user/me'的主要内容,如果未能解决你的问题,请参考以下文章

使用slim-jwt-auth生成令牌

升级后的 jwt-auth - 从请求令牌中获取用户

使用 slim-jwt-auth 生成令牌

Lumen:jwt-auth 不存在方法句柄,已完成中间件

.NET Framework MVC 和 Web Api Auth JWT

如何从 laravel 刀片访问 JWT?