Nodejs jwt 鉴权问题请教
之前 nodejs 里习惯用 session 做鉴权,验证通过 req.session 直接保存就可以了。后续不管是浏览器请求还是 ajax 都会拿到 session 。 现在打算改成 jwt ,看 w3c 标准说是放到 header 的 Authorization 里边,鉴权逻辑已经改好了,但是传递这个头信息有点麻烦。 例如: /login 验证完,json 返回 token ,后续 ajax 请求可以自己加 header ,但是浏览器直接访问的页面并不会主动带 Authorization 信息,直接访问某个 url 例如:/profile 还是未鉴权。
有没有办法全局修改浏览器在当前网站中的 Authorization 头信息呢?
Nodejs jwt 鉴权问题请教
jwt 鉴权一般只用于 API 上吧,没有直接访问 API URL 的场景。实在不行 access token 放 cookie 里也能接受
Authorization HEADER 这种授权模式本来就不是为了 Page 模式设计的,它主要是为了服务/服务通讯和 SPA 设计的。
没有办法全局设置浏览器的 Authorization, 一般如果的确需要使用顶级 GET 请求后端并附带权限,会再 query 字符串上添加 token=JwtToken 。如果你不是当页面,使用 cookie/session 模式才是更方便的。
我理解是请求接口才验证 jwt ,请求静态资源不校验 jwt 呀
封装一个全局请求方法带上 headers 参考 axios 全局拦截器
后端模拟前端登录
const template = <br> <!DOCTYPE html><br> <html lang="en"><br> <head><br> <meta charset="UTF-8"><br> <meta http-equiv="X-UA-Compatible" content="IE=edge"><br> <meta name="viewport" content="width=device-width, initial-scale=1.0"><br> <title></title><br> </head><br> <body><br> <script><br> const channel = new BroadcastChannel('response');<br> channel.postMessage(${JSON.stringify(params)})<br> window.close();<br> </script><br> </body><br> </html><br>
;
ctx.body = template;
直接放在 cookies 注意同源问题就行了。
jwt 为啥不能放 cookie 里,瞎搞扯,服务端为啥不能同时兼容 Authorization header 和 cookie 传递,这种标准本来就是推荐而已,既然不好用那不是给自己挖坑么
jwt 当然是放 cookie 里啊…
/login 验证完在 response 的 header 里加上 Set-Cookie: token=<jwtstring>
#7
确实,怎么传 jwt 是看业务需求,jwt 只能保证内容不会被篡改。
感谢大家的回复, 如果确实要改成 jwt 的话,看来只能 header+cookie 了。
typescript<br>import { BadRequestException, Injectable } from 'nestjs/common'<br>import { ConfigService } from 'nestjs/config'<br>import { Request } from 'express'<br>import { Strategy } from 'passport-jwt'<br>import { PassportStrategy } from 'nestjs/passport'<br>import { IToken } from '/user/auth/auth.decorator'<br><br>()<br>export class AuthJwtStrategy extends PassportStrategy(Strategy, 'jwt') {<br> constructor(configService: ConfigService) {<br> super({<br> jwtFromRequest: AuthJwtStrategy.fromCookieOrHeader,<br> secretOrKey: configService.get('JWT_SECRET'),<br> })<br> }<br><br> public static fromCookieOrHeader(req: Request): string {<br> const authHeader = req.header('authorization')<br> if (authHeader && authHeader.startsWith('Bearer ')) {<br> return authHeader.substring(7, authHeader.length)<br> }<br> return req.cookies['access_token']<br> }<br><br> // eslint-disable-next-line class-methods-use-this<br> public async validate(payload: IToken): Promise<IToken> {<br> if (payload.type !== 'access_token') {<br> throw new BadRequestException('token 类型无效')<br> }<br> return payload<br> }<br>}<br>
passport.js 里,passport-jwt 的 strategy 没有粗暴地从 header 取 authorization 字段而是暴露了 jwtFromRequest ,就是希望使用者可以灵活一点。
前端封装 HTTP 请求,如果使用 axios 之类的就更方便了
放那里都行,只要你后端能拿到
但是标准用法是放 header
不放 cookie 里是因为可以省去 csrf 防护
优先校验 header token ,没有的话看 referrer 为空+GET 则校验 cookie token
接口请求不携带 cookie ,页面 GET 请求会自动携带 cookie
这个需要弄个中间件维持吧
cookie 有安全问题的,你要加 csrf_token 才行。
其实 Cookie 在 SameSite 之后 CSRF 问题好了很多很多了
其实通用的就是登陆成功后把 token 放 cookie 里,大厂里通用的 sso 登陆也是,至于其他安全问题有专门的解决办法,比如 csrf
你说的 session 鉴权其实也是 node 框架把登录状态保存到了 cookie 里,然后服务端解析到之后又放在了 req 对象的 session 字段里方便后端处理。
HTML SSR 和 JWT 匹配不好
JWT 是个有期限且期限内不方便撤销的 secret, 让页面地址包含 JWT 等于把这个 secret 存到用户浏览记录里
不如不用 JWT
JSON Web Token (JWT) is a compact claims representation format
intended for space constrained environments such as HTTP
Authorization headers and URI query parameters.
https://www.rfc-editor.org/rfc/rfc7519
你的问题是如何传输 JWT 的问题,和 JWT 本身没有直接关系。
放 cookie 里
你就当写小程序就完了,小程序咋写 页面咋写,就是给请求多一层封装
按照标准的话,就自己封装请求器自己往头信息加。
其实可以改一下服务端的逻辑,从 cookie 中取出来后再验证,放 cookie 是没问题的,可以利用浏览器机制自动把信息带上去。
月经贴啊,放 cookie 方便,只是怕伪造请求,但是加 https only 限制 domain 的话其实也防住了, 放 header 可以 axios 统一封装,上面的楼也说过了。
jwt 并没限制放哪,既可以放 Authorization 头里,也可以放 cookie 里
axios 请求前拦截把 token 加入到 header 或者直接放到 cookie 中也可以,本身这个用法没有强制约束,只要你前后端协调好就可以
Token 也可以放在 HTTP 的 response 头里,比如用 authorization 头来返回给客户端。
客户端不管是浏览器页面还是 App ,都可以做一个统一的请求拦截器,负责管理 token ,在登陆成功后自动读取返回的 token 信息并存储在本地,拦截每一个发送的请求自动读取本地存储的 token 信息加在 authorization 头里,根据认证策略自动刷新即将过期的 token 。
比如你前端页面使用 axios 发送请求的话,可以看一下 axios 的 interceptors 相关文档。
op 不一定非要走这个 w3c 标准的,只要用了 token 其实就算是 jwt 了。
关于Node.js中使用JWT(JSON Web Token)进行鉴权的问题,这是一个常见的需求,通常用于验证用户的身份和权限。以下是一个基本的示例,展示如何在Node.js中使用JWT进行鉴权。
首先,确保你已经安装了必要的包:
npm install jsonwebtoken express body-parser
然后,你可以创建一个简单的Express服务器,用于生成和验证JWT:
const express = require('express');
const jwt = require('jsonwebtoken');
const bodyParser = require('body-parser');
const app = express();
const PORT = 3000;
const SECRET_KEY = 'your_secret_key';
app.use(bodyParser.json());
// 生成JWT
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 这里应该验证用户名和密码
if (username === 'admin' && password === 'password') {
const token = jwt.sign({ username }, SECRET_KEY, { expiresIn: '1h' });
res.json({ token });
} else {
res.status(401).send('Invalid Credentials');
}
});
// 验证JWT
const authenticateJWT = (req, res, next) => {
const token = req.headers.authorization && req.headers.authorization.split(' ')[1];
if (token == null) return res.sendStatus(401);
jwt.verify(token, SECRET_KEY, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
};
// 受保护的路由
app.get('/protected', authenticateJWT, (req, res) => {
res.json({ message: 'This is a protected route', user: req.user });
});
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
这个示例展示了如何生成JWT以及如何使用中间件来验证JWT。