之前 nodejs 里习惯用 session 做鉴权,验证通过 req.session 直接保存就可以了。后续不管是浏览器请求还是 ajax 都会拿到 session 。 现在打算改成 jwt ,看 w3c 标准说是放到 header 的 Authorization 里边,鉴权逻辑已经改好了,但是传递这个头信息有点麻烦。 例如: /login 验证完,json 返回 token ,后续 ajax 请求可以自己加 header ,但是浏览器直接访问的页面并不会主动带 Authorization 信息,直接访问某个 url 例如:/profile 还是未鉴权。
有没有办法全局修改浏览器在当前网站中的 Authorization 头信息呢?
1
hsfzxjy 2023-07-11 13:57:03 +08:00 via Android
jwt 鉴权一般只用于 API 上吧,没有直接访问 API URL 的场景。实在不行 access token 放 cookie 里也能接受
|
2
thinkershare 2023-07-11 13:59:43 +08:00
Authorization HEADER 这种授权模式本来就不是为了 Page 模式设计的,它主要是为了服务/服务通讯和 SPA 设计的。
没有办法全局设置浏览器的 Authorization, 一般如果的确需要使用顶级 GET 请求后端并附带权限,会再 query 字符串上添加 token=JwtToken 。如果你不是当页面,使用 cookie/session 模式才是更方便的。 |
3
LandCruiser 2023-07-11 14:00:06 +08:00
我理解是请求接口才验证 jwt ,请求静态资源不校验 jwt 呀
|
4
dreasky 2023-07-11 14:02:58 +08:00
封装一个全局请求方法带上 headers 参考 axios 全局拦截器
|
5
baiheinet 2023-07-11 14:04:01 +08:00
后端模拟前端登录
const template = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title></title> </head> <body> <script> const channel = new BroadcastChannel('response'); channel.postMessage(${JSON.stringify(params)}) window.close(); </script> </body> </html> `; ctx.body = template; |
6
victimsss 2023-07-11 14:05:45 +08:00 1
直接放在 cookies 注意同源问题就行了。
|
7
sujin190 2023-07-11 14:08:27 +08:00
jwt 为啥不能放 cookie 里,瞎搞扯,服务端为啥不能同时兼容 Authorization header 和 cookie 传递,这种标准本来就是推荐而已,既然不好用那不是给自己挖坑么
|
8
NessajCN 2023-07-11 14:10:46 +08:00 1
jwt 当然是放 cookie 里啊....
/login 验证完在 response 的 header 里加上 Set-Cookie: token=<jwtstring> |
10
cnfczn OP 感谢大家的回复, 如果确实要改成 jwt 的话,看来只能 header+cookie 了。
|
11
StrangerA 2023-07-11 14:15:41 +08:00
```typescript
import { BadRequestException, Injectable } from '@nestjs/common' import { ConfigService } from '@nestjs/config' import { Request } from 'express' import { Strategy } from 'passport-jwt' import { PassportStrategy } from '@nestjs/passport' import { IToken } from '@/user/auth/auth.decorator' @Injectable() export class AuthJwtStrategy extends PassportStrategy(Strategy, 'jwt') { constructor(configService: ConfigService) { super({ jwtFromRequest: AuthJwtStrategy.fromCookieOrHeader, secretOrKey: configService.get('JWT_SECRET'), }) } public static fromCookieOrHeader(req: Request): string { const authHeader = req.header('authorization') if (authHeader && authHeader.startsWith('Bearer ')) { return authHeader.substring(7, authHeader.length) } return req.cookies['access_token'] } // eslint-disable-next-line class-methods-use-this public async validate(payload: IToken): Promise<IToken> { if (payload.type !== 'access_token') { throw new BadRequestException('token 类型无效') } return payload } } ``` passport.js 里,passport-jwt 的 strategy 没有粗暴地从 header 取 authorization 字段而是暴露了 jwtFromRequest ,就是希望使用者可以灵活一点。 |
12
BreadKiller 2023-07-11 14:16:20 +08:00
前端封装 HTTP 请求,如果使用 axios 之类的就更方便了
|
13
estk 2023-07-11 14:31:56 +08:00
放那里都行,只要你后端能拿到
但是标准用法是放 header |
14
walpurgis 2023-07-11 14:43:31 +08:00 via iPhone 1
不放 cookie 里是因为可以省去 csrf 防护
|
15
FrankAdler 2023-07-11 14:46:02 +08:00
我这边是 cookie 、header 、get 参数顺序检查,同时兼顾 App 、Api 、前端的情况
|
16
jiangzm 2023-07-11 14:54:10 +08:00
优先校验 header token ,没有的话看 referrer 为空+GET 则校验 cookie token
接口请求不携带 cookie ,页面 GET 请求会自动携带 cookie |
17
Tyaqing 2023-07-11 18:25:22 +08:00
这个需要弄个中间件维持吧
|
18
FrankFang128 2023-07-11 19:13:00 +08:00
cookie 有安全问题的,你要加 csrf_token 才行。
|
20
LawlietZ 2023-07-11 19:29:35 +08:00
其实通用的就是登陆成功后把 token 放 cookie 里,大厂里通用的 sso 登陆也是,至于其他安全问题有专门的解决办法,比如 csrf
|
21
LawlietZ 2023-07-11 19:31:04 +08:00
你说的 session 鉴权其实也是 node 框架把登录状态保存到了 cookie 里,然后服务端解析到之后又放在了 req 对象的 session 字段里方便后端处理。
|
22
momocraft 2023-07-11 19:38:28 +08:00
HTML SSR 和 JWT 匹配不好
JWT 是个有期限且期限内不方便撤销的 secret, 让页面地址包含 JWT 等于把这个 secret 存到用户浏览记录里 不如不用 JWT |
23
lologame 2023-07-11 19:38:58 +08:00
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 本身没有直接关系。 |
24
lonisletend 2023-07-11 19:50:22 +08:00
|
25
lucifer1108 2023-07-11 19:53:22 +08:00
放 cookie 里
|
26
kingjpa 2023-07-11 19:55:10 +08:00
你就当写小程序就完了,小程序咋写 页面咋写,就是给请求多一层封装
|
27
keyframes 2023-07-11 20:00:03 +08:00
按照标准的话,就自己封装请求器自己往头信息加。
其实可以改一下服务端的逻辑,从 cookie 中取出来后再验证,放 cookie 是没问题的,可以利用浏览器机制自动把信息带上去。 |
28
webcape233 2023-07-11 20:06:35 +08:00 via iPhone
月经贴啊,放 cookie 方便,只是怕伪造请求,但是加 https only 限制 domain 的话其实也防住了, 放 header 可以 axios 统一封装,上面的楼也说过了。
|
29
ysc3839 2023-07-11 21:30:35 +08:00 via Android
jwt 并没限制放哪,既可以放 Authorization 头里,也可以放 cookie 里
|
30
layxy 2023-07-12 09:31:41 +08:00
axios 请求前拦截把 token 加入到 header 或者直接放到 cookie 中也可以,本身这个用法没有强制约束,只要你前后端协调好就可以
|
31
libook 2023-07-13 17:37:14 +08:00
Token 也可以放在 HTTP 的 response 头里,比如用 authorization 头来返回给客户端。
客户端不管是浏览器页面还是 App ,都可以做一个统一的请求拦截器,负责管理 token ,在登陆成功后自动读取返回的 token 信息并存储在本地,拦截每一个发送的请求自动读取本地存储的 token 信息加在 authorization 头里,根据认证策略自动刷新即将过期的 token 。 比如你前端页面使用 axios 发送请求的话,可以看一下 axios 的 interceptors 相关文档。 |
32
chuck1in 2023-07-18 12:48:22 +08:00
op 不一定非要走这个 w3c 标准的,只要用了 token 其实就算是 jwt 了。
|