如何在重定向页面时将jwt存储在cookie中并将其传递给身份验证功能?

时间:2019-06-10 10:05:41

标签: node.js express jwt handlebars.js postman

我有一个用Postman构建并用Jest测试过的node.js Express后端。我用hbs编写了一个前端,下一步是缝合它们。但是,我仍然不断收到来自auth函数的“请验证”错误消息,我猜这是因为我没有成功传递jwt令牌。

所以在登录页面(用户/登录)上,我想用电子邮件和密码登录,然后我想重定向到我的页面(用户/我),在这里我可以执行属于该用户的其他操作。

前端 登录页面代码:

<section class="login-bg">
        <div class="login-form">
            <p>Welcome to Task Manager, please log in!</p>
            <form class="input-group" action="/users/login" method="POST">
                <label>Email:</label>
                <input type="email" name="email" placeholder="type your email" value="{‌{user.email}}" required >
                <label>Password:</label>
                <input type="password" name="password" placeholder="type your password" value="{‌{user.password}}" required>

                <button class="button" type="submit">Log In</button>
            </form>
        </div>
    </section>

后端

在middleware / auth.js中

const jwt = require('jsonwebtoken')
const User = require('../models/user')

const auth = async (req, res, next) => {
    try {
        const token = req.header('Authorization').replace('Bearer ', '')
        const decoded = jwt.verify(token, process.env.JWT_SECRET)
        const user = await User.findOne({_id: decoded._id, 'tokens.token': token})

        if (!user) {
            throw new Error()
        }

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

    } catch (error) {
        res.status(401).send({error: 'Please authenticate.'})
    }
}

module.exports = auth

在src / routers / users.js中

router.post('/login', async (req, res) => {
    try {
        const user = await User.findByCredentials(req.body.email, req.body.password)
        const token = await user.generateAuthToken()
        res.cookie('jwt',token, { httpOnly: true, secure: true, maxAge: 3600000 })
        res.redirect('/users/me')
    } catch (error) {
        res.status(400).send()
    }
})

但是,当我在users / me中执行console.log(document.cookie)时,它表示未定义。

然后我安装了cookie解析器,并将其导入到app.js中,并尝试在src / routers / users.js中编写此部分:

router.get('/me', auth, async (req, res) => {
    console.log('Cookies: ', req.cookies)
    try {
        res.render('me', {name: user.name})
    } catch (error) {
        res.status(500).send()
    }
})

但是此控制台无法打印任何内容,可能是因为我从auth中收到错误消息。

我的页面上还附有一个js文件,但是我不知道是否可以这样写,可能是错误的:

const userToken = document.cookie.jwt.token

fetch('/users/me', {
    method: 'POST',
    headers: {
     'Authorization': 'Bearer ' + userToken
    }
})
.then(res => res.json())
.then(data => { console.log(data) })
.catch(err => { console.log(err) })

然后在“网络/标题”中,我有

请求网址:

http://localhost:3000/users/login

请求方法:

开机自检

状态码:

找到302

远程地址:

推荐人政策:

降级时无推荐人

响应标题

连接:

保持生命

内容长度:

62

内容类型:

text / html; charset = utf-8

日期:

2019年6月7日星期五18:41:47 GMT

位置:

/ users / me

Set-Cookie:

JWT = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1Y2Y2NjNlMTQwMTQyYjE0MzhmZTJjNDMiLCJpYXQiOjE1NTk5MzI5MDd9.T_P8O-j98cs9gtahTzspJjx1qNMSe3M5OAySyeH25fs;最大年龄= 3600;路径= /; Expires = Fri,2019年6月7日19:41:47 GMT; HttpOnly;安全

不同:

接受

X-Powered-By:

快递

没有请求cookie,只有响应cookie。我不确定这意味着什么... @ _ @

我想通过jwt来成功登录并正确渲染我页面,我该怎么做?

3 个答案:

答案 0 :(得分:1)

首先:您无法在客户端上查看Cookie,因为您设置了以下内容({secure:true,httpOnly:true}) -secure表示它仅应在https网络上使用cookie -httpOnly表示该cookie应该由任何客户端Javascript读取。

第二:您是在生成jwt之后确实添加了“授权”标头,还是只是将其放入Cookie中?

如果是这样,请尝试:

jwt.verify(token, <your secret>).then(user=> console.log(user)).catch(err=>console.log(err.toString());

对于那些将来可能会遇到相同问题的人

答案 1 :(得分:0)

您的jwt令牌cookie不起作用,因为它在以下代码中声明了标志secure: true

res.cookie('jwt',token, { httpOnly: true, secure: true, maxAge: 3600000 })

在HTTP响应中导致Secure标志,表明此cookie仅在HTTPS环境下可用:

Set-Cookie:
jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1Y2Y2NjNlMTQwMTQyYjE0MzhmZTJjNDMiLCJpYXQiOjE1NTk5MzI5MDd9.T_P8O-j98cs9gtahTzspJjx1qNMSe3M5OAySyeH25fs; 
Max-Age=3600; Path=/; 
Expires=Fri, 07 Jun 2019 19:41:47 GMT; HttpOnly; Secure

由于您的请求URL使用HTTP(http://localhost:3000/users/login),因此浏览器将忽略该Cookie。

答案 2 :(得分:0)

摘自Express-Session文档:

仅在生产时设置安全标签。

    if (app.get('env') === 'production') {
      app.set('trust proxy', 1) // trust first proxy
      sess.cookie.secure = true // serve secure cookies
    }