V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cnfczn
V2EX  ›  Node.js

请教个 jwt 鉴权的问题

  •  
  •   cnfczn · 317 天前 · 3445 次点击
    这是一个创建于 317 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

    接口请求不携带 cookie ,页面 GET 请求会自动携带 cookie
    Tyaqing
        17
    Tyaqing  
       317 天前
    这个需要弄个中间件维持吧
    FrankFang128
        18
    FrankFang128  
       317 天前
    cookie 有安全问题的,你要加 csrf_token 才行。
    retanoj
        19
    retanoj  
       317 天前
    @walpurgis 其实 Cookie 在 SameSite 之后 CSRF 问题好了很多很多了
    LawlietZ
        20
    LawlietZ  
       317 天前
    其实通用的就是登陆成功后把 token 放 cookie 里,大厂里通用的 sso 登陆也是,至于其他安全问题有专门的解决办法,比如 csrf
    LawlietZ
        21
    LawlietZ  
       317 天前
    你说的 session 鉴权其实也是 node 框架把登录状态保存到了 cookie 里,然后服务端解析到之后又放在了 req 对象的 session 字段里方便后端处理。
    momocraft
        22
    momocraft  
       317 天前
    HTML SSR 和 JWT 匹配不好

    JWT 是个有期限且期限内不方便撤销的 secret, 让页面地址包含 JWT 等于把这个 secret 存到用户浏览记录里
    不如不用 JWT
    lologame
        23
    lologame  
       317 天前
    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 本身没有直接关系。
    lonisletend
        24
    lonisletend  
       317 天前

    我请求用的是 axios, 可以这么封装, 登录之后写 setToken, 需要注意的是, setToken 里必须再设置一下 axios.defaults.headers.common['Authorization'], 否则登录之后紧接着的其他请求不会带着 token, 没查到为啥, 所以设置一下比较保险, 之后所有的使用 axios 的请求都会带着 token 了.
    lucifer1108
        25
    lucifer1108  
       317 天前
    放 cookie 里
    kingjpa
        26
    kingjpa  
       317 天前
    你就当写小程序就完了,小程序咋写 页面咋写,就是给请求多一层封装
    keyframes
        27
    keyframes  
       317 天前
    按照标准的话,就自己封装请求器自己往头信息加。
    其实可以改一下服务端的逻辑,从 cookie 中取出来后再验证,放 cookie 是没问题的,可以利用浏览器机制自动把信息带上去。
    webcape233
        28
    webcape233  
       317 天前 via iPhone
    月经贴啊,放 cookie 方便,只是怕伪造请求,但是加 https only 限制 domain 的话其实也防住了, 放 header 可以 axios 统一封装,上面的楼也说过了。
    ysc3839
        29
    ysc3839  
       317 天前 via Android
    jwt 并没限制放哪,既可以放 Authorization 头里,也可以放 cookie 里
    layxy
        30
    layxy  
       317 天前
    axios 请求前拦截把 token 加入到 header 或者直接放到 cookie 中也可以,本身这个用法没有强制约束,只要你前后端协调好就可以
    libook
        31
    libook  
       315 天前
    Token 也可以放在 HTTP 的 response 头里,比如用 authorization 头来返回给客户端。
    客户端不管是浏览器页面还是 App ,都可以做一个统一的请求拦截器,负责管理 token ,在登陆成功后自动读取返回的 token 信息并存储在本地,拦截每一个发送的请求自动读取本地存储的 token 信息加在 authorization 头里,根据认证策略自动刷新即将过期的 token 。

    比如你前端页面使用 axios 发送请求的话,可以看一下 axios 的 interceptors 相关文档。
    chuck1in
        32
    chuck1in  
       311 天前
    op 不一定非要走这个 w3c 标准的,只要用了 token 其实就算是 jwt 了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3507 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 41ms · UTC 05:12 · PVG 13:12 · LAX 22:12 · JFK 01:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.