请教个 jwt 鉴权的问题

2023-07-11 13:52:54 +08:00
 cnfczn

之前 nodejs 里习惯用 session 做鉴权,验证通过 req.session 直接保存就可以了。后续不管是浏览器请求还是 ajax 都会拿到 session 。 现在打算改成 jwt ,看 w3c 标准说是放到 header 的 Authorization 里边,鉴权逻辑已经改好了,但是传递这个头信息有点麻烦。 例如: /login 验证完,json 返回 token ,后续 ajax 请求可以自己加 header ,但是浏览器直接访问的页面并不会主动带 Authorization 信息,直接访问某个 url 例如:/profile 还是未鉴权。

有没有办法全局修改浏览器在当前网站中的 Authorization 头信息呢?

3782 次点击
所在节点    Node.js
32 条回复
hsfzxjy
2023-07-11 13:57:03 +08:00
jwt 鉴权一般只用于 API 上吧,没有直接访问 API URL 的场景。实在不行 access token 放 cookie 里也能接受
thinkershare
2023-07-11 13:59:43 +08:00
Authorization HEADER 这种授权模式本来就不是为了 Page 模式设计的,它主要是为了服务/服务通讯和 SPA 设计的。
没有办法全局设置浏览器的 Authorization, 一般如果的确需要使用顶级 GET 请求后端并附带权限,会再 query 字符串上添加 token=JwtToken 。如果你不是当页面,使用 cookie/session 模式才是更方便的。
LandCruiser
2023-07-11 14:00:06 +08:00
我理解是请求接口才验证 jwt ,请求静态资源不校验 jwt 呀
dreasky
2023-07-11 14:02:58 +08:00
封装一个全局请求方法带上 headers 参考 axios 全局拦截器
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;
victimsss
2023-07-11 14:05:45 +08:00
直接放在 cookies 注意同源问题就行了。
sujin190
2023-07-11 14:08:27 +08:00
jwt 为啥不能放 cookie 里,瞎搞扯,服务端为啥不能同时兼容 Authorization header 和 cookie 传递,这种标准本来就是推荐而已,既然不好用那不是给自己挖坑么
NessajCN
2023-07-11 14:10:46 +08:00
jwt 当然是放 cookie 里啊....
/login 验证完在 response 的 header 里加上 Set-Cookie: token=<jwtstring>
flyqie
2023-07-11 14:12:35 +08:00
@sujin190 #7

确实,怎么传 jwt 是看业务需求,jwt 只能保证内容不会被篡改。
cnfczn
2023-07-11 14:14:44 +08:00
感谢大家的回复, 如果确实要改成 jwt 的话,看来只能 header+cookie 了。
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 ,就是希望使用者可以灵活一点。
BreadKiller
2023-07-11 14:16:20 +08:00
前端封装 HTTP 请求,如果使用 axios 之类的就更方便了
estk
2023-07-11 14:31:56 +08:00
放那里都行,只要你后端能拿到
但是标准用法是放 header
walpurgis
2023-07-11 14:43:31 +08:00
不放 cookie 里是因为可以省去 csrf 防护
FrankAdler
2023-07-11 14:46:02 +08:00
我这边是 cookie 、header 、get 参数顺序检查,同时兼顾 App 、Api 、前端的情况
jiangzm
2023-07-11 14:54:10 +08:00
优先校验 header token ,没有的话看 referrer 为空+GET 则校验 cookie token

接口请求不携带 cookie ,页面 GET 请求会自动携带 cookie
Tyaqing
2023-07-11 18:25:22 +08:00
这个需要弄个中间件维持吧
FrankFang128
2023-07-11 19:13:00 +08:00
cookie 有安全问题的,你要加 csrf_token 才行。
retanoj
2023-07-11 19:27:14 +08:00
@walpurgis 其实 Cookie 在 SameSite 之后 CSRF 问题好了很多很多了
LawlietZ
2023-07-11 19:29:35 +08:00
其实通用的就是登陆成功后把 token 放 cookie 里,大厂里通用的 sso 登陆也是,至于其他安全问题有专门的解决办法,比如 csrf

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/955809

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX