如何使用 express 在用户浏览器的响应标头 cookie 中查找 JSON Web 令牌 (JWT) 来制作 node.js?
Posted
技术标签:
【中文标题】如何使用 express 在用户浏览器的响应标头 cookie 中查找 JSON Web 令牌 (JWT) 来制作 node.js?【英文标题】:How do I make node.js using express find a JSON Web Token (JWT) inside of a response header cookie in user's browser? 【发布时间】:2021-11-19 09:01:09 【问题描述】:我有一个关于如何在用户的浏览器 cookie 中搜索我的 JWT 令牌的问题。
下面我有一些代码在响应标头中搜索用户浏览器中的 cookie,但我不确定如何使代码更具体并在 cookie 中搜索 JWT 令牌并验证它是否是实际的 JWT 令牌这是分配给该用户的。
const jwt = require('jsonwebtoken');
const router = require('express')();
const cookieParser = require('cookie-parser');
router.use(cookieParser());
module.exports = function(req,res,next)
const token = req.header('Cookie');
if (!token)
return res.status(403).send('Access Denied');
try
const verified = req.header('Cookie');
req.user = verified;
// const verified = jwt.verify(token, process.env.TOKEN_SECRET);
// req.user = verified;
next();
catch (err)
res.clearHeader;
res.status(403).send('Invalid Token');
;
【问题讨论】:
【参考方案1】:希望我没有误解你的问题并浪费了很多时间。
简答:如何检索信息
使用req.body
或req.headers
。如果某些内容将包含令牌或身份验证详细信息,那么它就是这两者之一。
完整的身份验证演练:
要获取 JSON Web 令牌,您首先必须生成它们。不过,不建议实施您自己的令牌身份验证。我将在这里逐步展示如何创建一个完整的身份验证系统。
为简单起见,假设我们在文件auth.js
中有一个导出的route
,这个路由将是一个子路由domain.com/auth
,一个包含所有活动refreshTokens
和jwt
的数组:
const express = require("express")
const jwt = require("jsonwebtoken")
let route = (exports.route = express())
let refreshTokens = []
我们要做的是生成一个持久的刷新令牌,用户可以使用它来生成一个较小的 15 分钟访问令牌。之后,您使用刷新令牌等生成新的访问令牌。但要获得刷新令牌,您需要登录或注册。用户还可以注销并杀死刷新令牌。
route.post("/token", async (req, res) =>
// Input: Refresh Token
// Output: Access Token Generation
)
route.post("/login", async (req, res) =>
// Input: User, Password
// Output: Refresh Token
)
route.delete("/logout", async (req, res) =>
// Input: Token to Remove
)
让我们从结尾开始。你有一个刷新令牌,你不会销毁它。只需根据此令牌过滤数组并提交状态。令牌从数组中清除后变得无法使用,这就是这里的目标。
route.delete("/logout", async (req, res) =>
refreshTokens = refreshTokens.filter((token) => token != req.body.token)
res.sendStatus(204)
)
到目前为止和我在一起?现在让我们回到开始。如果您使用电子邮件和密码登录,如果错误则回复错误消息,如果正确则接收令牌。
route.post("/login", async (req, res) =>
const username = req.body.username
const password = req.body.password
// This is just a quick demonstration,
// you would have to use the bcrypt hash
// or other hash/salt methods. DO NOT
// STORE passwords plaintext
// Not existent user = Unauthorized
if (username != 'admin') return res.sendStatus(401)
// Wrong Password = Forbidden
if (password != 'abc123') return res.sendStatus(403)
const user =
id: 0,
username: username,
password: password
const accessToken = generateAccessToken(user)
const refreshToken = generateRefreshToken(user)
let result =
success: true,
accessToken: accessToken,
refreshToken: refreshToken,
res.send(result)
)
现在我们如何签署 JSON 网络令牌?我们来看看这里使用的两种方法:
function generateAccessToken(content)
return jwt.sign(content, process.env.ACCESS_TOKEN_SECRET,
expiresIn: "15m",
)
function generateRefreshToken(content)
const token = jwt.sign(content, process.env.REFRESH_TOKEN_SECRET)
refreshTokens.push(token)
return token
两者都使用某种环境标记,但为什么呢?这就是您必须为后端生成一次的令牌。它将用作公钥。我们只需生成 15 分钟的访问令牌并将刷新令牌推送到数组。
route.post("/token", async (req, res) =>
const refreshToken = req.body.token
if (refreshToken == null) return res.sendStatus(401)
if (!refreshTokens.includes(refreshToken)) return res.sendStatus(403)
jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, user) =>
if (err) return res.sendStatus(403)
res.json( accessToken:
generateAccessToken(
id: 0,
username: user.name,
password: user.password
)
)
)
)
我们验证刷新令牌,如果存在且有效,则返回一个新的访问令牌 15 分钟。令牌部分就是这样,您可以登录(创建刷新令牌)、检索访问令牌和注销(杀死刷新令牌)
使用方法:认证授权
无论您是以访客身份还是实际用户登录,管理页面都应该返回 403,而论坛板块应该有所不同。第一个是认证,第二个是授权。
让我们为每个函数创建两个函数。 Express 使用 next()
功能非常方便
exports.authenticate = function (req, res, next)
const authHeader = req.headers["authorization"]
const token = authHeader?.split(" ")[1]
jwt.verify(token || "", process.env.ACCESS_TOKEN_SECRET, (err, user) =>
req.user = err ? : user
next()
);
;
exports.authorize = function (req, res, next)
const authHeader = req.headers["authorization"]
const token = authHeader?.split(" ")[1]
if (token == null)
return res.sendStatus(401)
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) =>
if (err) return res.sendStatus(403)
req.user = user
next()
)
现在您已经完成了整个身份验证系统(除了一些清理工作),可能还有注册系统。让我们利用它。
客户端你可以像这样创建一个 REST api:
POST http://localhost:8081/auth/login
Content-Type: application/json
"username": "admin",
"password": "abc123"
# Returns refresh and access token.
###
DELETE http://localhost:8081/auth/logout
Content-Type: application/json
"token": "REFRESH_TOKEN"
# Logs out a user.
###
POST http://localhost:8081/auth/token
Content-Type: application/json
"token": "REFRESH_TOKEN"
#
# This is how you can provide the access token
# when making a request to say a forum api
#
GET http://localhost:8081/forum/api/board/0
Authorization: Bearer ACCESS_TOKEN
用法:
route.get("forum/board/:id", authenticate, async (req, res) =>
res.send(req.user)
)
去localhost:8081/forum/board/7
认证时的预期输出:
id:0,username:"admin",password:"abc123"
否则:
尽管如此,请勿尝试实施您自己的身份验证。真的,你不应该。
来源
https://www.youtube.com/watch?v=mbsmsi7l3r4
【讨论】:
以上是关于如何使用 express 在用户浏览器的响应标头 cookie 中查找 JSON Web 令牌 (JWT) 来制作 node.js?的主要内容,如果未能解决你的问题,请参考以下文章
如何将授权标头添加到用户请求并使用 express 将其代理到另一个服务器 api
可以使用 launchSettings.json 启用 IIS Express 的 access-control-allow-origin 响应标头吗?