无法使用 Express 和 Angular 将 JWT 存储在 Cookie 中

Posted

技术标签:

【中文标题】无法使用 Express 和 Angular 将 JWT 存储在 Cookie 中【英文标题】:Can't store JWT in Cookie with Express & Angular 【发布时间】:2020-11-22 18:56:03 【问题描述】:

过去几天我一直在拔头发。无论我在 Google 上搜索多少次都找不到答案,所以我作为最后的手段来到这里,希望得到一些帮助。

我正在 MEAN 堆栈上创建一个完整的堆栈应用程序。我的登录有效。它正在验证电子邮件和密码是否与我的数据库中用户的电子邮件和密码匹配。现在我想向我的客户发送一个 JWT 令牌,这样我就可以让用户登录。我了解 JWT 的工作原理,并且我已经生成了一个

 const ACCESS_TOKEN_SECRET = "a random string";
 const payload = "username": login_result[0].username; 
 const accessToken = jwt.sign(payload, ACCESS_TOKEN_SECRET);

这就是我的问题开始的地方。我想将令牌存储在 cookie 中,以防止 XSS 攻击。我尝试了各种方法将 JWT 存储在 cookie 中。大多数论坛都写我应该这样做

res.cookie('access_token', accessToken);

据我了解,这应该会自动将 JWT 存储在我的客户端上名为“access_token”的 cookie 中。但是,这不起作用。当这一行出现在代码中时,什么都没有发生。 “什么都没有发生”是指客户端代码没有执行。

如果密码/电子邮件无效,我会返回错误代码。

if(res.msg == "403")
        this.showLogErrorMsg = true;
      

这部分有效。

else 语句如下所示 别的 console.log("有效的用户名和密码");

    window.location.href = "http://localhost:4200/profile";

  

意思是,如果登录错误,它会打印一个错误(确实如此),如果登录正确,他们应该被重定向。这不起作用。当我这样做时它确实有效

ret.json("access_token":accessToken); 

但不适用于

   res.cookie('access_token', accessToken); 

这是我不明白的。它不将 access_token 存储在 cookie 中,也不执行 else 语句中的代码。我的服务器或客户端上没有错误消息。此外,每个指南或教程都说要使用 res.cookie,因为我使用 Express 作为我的网络服务器。 我什至尝试添加以下选项:

    res.cookie('access_token', accessToken,domain: domain, path: '/',httpOnly:false, 
               secure:false,sameSite:false);

解决方案是,以某种方式使 res.cookies 工作,我真的很想这样做,因为它是“其他人都在使用的”,而且看起来真的很冷。或者,将 JWT 令牌作为 res.json 发送,然后将令牌保存到 Angular 的 cookie 中。然而,这会让你为 XSS 敞开心扉吗?如果没有,我怎样才能以角度将某些东西保存到 cookie 中?

提前谢谢你们。

【问题讨论】:

您能否确认Set-Cookie 标头已被客户端正确接收? (开发工具 > 网络) 我不相信有 Set-Cookie 标头。我对网络部分不是很精通,所以我将链接一些屏幕截图。当我尝试使用正确的用户名/密码登录时,网络部分会发生这种情况:prntscr.com/tsppq6prntscr.com/tspq1iprntscr.com/tspq55 请问,Set-Cookie 标头是什么? Set-Cookie 是告诉客户端保存域信息的标头。当您使用 express 并调用 res.cookie('COOKIE_NAME',...) 时,它(应该)生成一个 Set-Cookie 标头来携带并将该数据设置给客户端。要对此进行测试,请创建最简单的端点并设置 cookie(删除中间件是未设置标头)。 @Daniel 我非常不确定如何“创建最简单的端点并设置 cookie(删除中间件是未设置标头)”。您的意思是,使用 express(后端)创建一个网络服务器并将 cookie 发送到随机前端组件(客户端),而不对我的数据库进行任何“花哨”验证? 是的。如果您的问题是设置 Cookie,请尝试将问题简化为最简单的形式 【参考方案1】:

这是一个基本的express 应用程序,用于设置、取消设置和显示 cookie。

设置GET /login 未设置GET /logout 显示GET /

这不依赖于客户端(角度)

# main.js
const express = require('express')
const cookieParser = require('cookie-parser')

const app = express()
app.use(cookieParser())

const port = 3000
const accessToken = 'XXXXXXXXXXXXXXXXXXXXX';

app.get('/', (req, res) => 
    res.json(req.cookies)
);

app.get('/login', (req, res) => 
    res.cookie('access_token', accessToken,  path: '/', httpOnly: true, sameSite: "strict" )
    res.send('"access_token" cookies was set !')
);

app.get('/logout', (req, res) => 
    res.cookie('access_token', accessToken,  maxAge: 0 )
    res.send('"access_token" cookies was unset !')
);

app.listen(port, () => 
    console.log(`Example app listening at http://localhost:$port`)
);

【讨论】:

谢谢@Daniel。看来问题是,我需要使用 GET 请求来设置 cookie?如果我将您的代码更改为 POST(就像我的代码一样),它将添加 SET-COOKIE 标头,但不显示 cookie。但是,如果我使用 GET 请求,它会在我的浏览器中设置 cookie。无论如何,我可以通过 POST 请求来做到这一点? 通过进一步的测试,它似乎也不总是在 GET 请求上设置 cookie。我必须进入网络并在它想要显示 cookie 之前单击包...我可以在标题中看到 Set-Cookie,但在我的应用程序 > Cookies 中看不到它,然后单击自己打包。 我上传了一个显示完整流程的 GIF wetransfer.com/downloads/…

以上是关于无法使用 Express 和 Angular 将 JWT 存储在 Cookie 中的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Angular 7 将授权标头发送到节点 11/Express 4 服务器

无法将 Express.js 服务器连接到 Angular 前端

Angular 1.5.6 和没有 Express 的路由

无法使 PUT 方法工作(Express & Angular)

使用 Mongo/Express/Angular/Node 推送到模型中的数组

Node、Angular、Express 和视图引擎