请教个 jwt 鉴权的问题

303 天前
 cnfczn

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

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

3425 次点击
所在节点    Node.js
32 条回复
hsfzxjy
303 天前
jwt 鉴权一般只用于 API 上吧,没有直接访问 API URL 的场景。实在不行 access token 放 cookie 里也能接受
thinkershare
303 天前
Authorization HEADER 这种授权模式本来就不是为了 Page 模式设计的,它主要是为了服务/服务通讯和 SPA 设计的。
没有办法全局设置浏览器的 Authorization, 一般如果的确需要使用顶级 GET 请求后端并附带权限,会再 query 字符串上添加 token=JwtToken 。如果你不是当页面,使用 cookie/session 模式才是更方便的。
LandCruiser
303 天前
我理解是请求接口才验证 jwt ,请求静态资源不校验 jwt 呀
dreasky
303 天前
封装一个全局请求方法带上 headers 参考 axios 全局拦截器
baiheinet
303 天前
后端模拟前端登录

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
303 天前
直接放在 cookies 注意同源问题就行了。
sujin190
303 天前
jwt 为啥不能放 cookie 里,瞎搞扯,服务端为啥不能同时兼容 Authorization header 和 cookie 传递,这种标准本来就是推荐而已,既然不好用那不是给自己挖坑么
NessajCN
303 天前
jwt 当然是放 cookie 里啊....
/login 验证完在 response 的 header 里加上 Set-Cookie: token=<jwtstring>
flyqie
303 天前
@sujin190 #7

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

接口请求不携带 cookie ,页面 GET 请求会自动携带 cookie
Tyaqing
302 天前
这个需要弄个中间件维持吧
FrankFang128
302 天前
cookie 有安全问题的,你要加 csrf_token 才行。
retanoj
302 天前
@walpurgis 其实 Cookie 在 SameSite 之后 CSRF 问题好了很多很多了
LawlietZ
302 天前
其实通用的就是登陆成功后把 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