V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
sdbybyd
V2EX  ›  Java

请教大家 WebSocket 鉴权问题

  •  1
     
  •   sdbybyd · Oct 4, 2020 · 9354 views
    This topic created in 2042 days ago, the information mentioned may be changed or developed.

    目前项目用 jwt 做 http 的鉴权,保存在 cookie 中,但是 websocket 不能使用 httponly 的 cookie, 看了淘宝还有 fb 的方案,都是用 url 参数带个 token 或者 sessionId 过去后端, 请教下前端如何获取这个发送的 token,或者 ssid,直接请求后台:GET /token 获取吗?这样是否安全

    23 replies    2020-10-06 21:36:35 +08:00
    ila
        1
    ila  
       Oct 4, 2020 via Android
    wss,每次请求加上 token
    wd
        2
    wd  
       Oct 4, 2020 via iPhone
    websocket 按说也是个 http 你可以在 upgrade 连接前判断好 不合规就给它断开
    wd
        3
    wd  
       Oct 4, 2020 via iPhone
    哦 http olny 好吧..
    leyle
        4
    leyle  
       Oct 4, 2020
    ws 是个长连接。可以先允许任何 client 与 server 建立连接,然后 server 判断当前用户是否鉴权。
    正常请求下,ws client 发起对 server 的连接后,就能够主动 /被动的发送 token 给 server 。
    server 可以对未发送 token 的 client 发送要求发送 token 的“指令”,如果在一个 X 秒内没有收到 client 发送过来的 token,server 就可以主动断开连接。如果同一个 client 多次发起连接且没有鉴权成功,就用其他机制限制链接一段时间。
    sdbybyd
        5
    sdbybyd  
    OP
       Oct 4, 2020
    @leyle 这个 token 怎么来呢,重 cookie 提取吗? httoonly 的 cookie 没办法
    sdbybyd
        6
    sdbybyd  
    OP
       Oct 4, 2020
    @wd 这个思路有想过 不过感觉还是有点奇怪
    JimmyChange
        7
    JimmyChange  
       Oct 4, 2020 via iPhone
    在建立 websocket 链接的请求可以读取 cookie 吧?就是需要返回 101 的那个请求里

    要是使用 token,直接提供给 api 获取 token 就好了吧
    Arrowing
        8
    Arrowing  
       Oct 4, 2020
    有个思路不知道行不行
    就是客户端请求服务器的时候,将客户端特征信息(记为 ID )保存下来,保证唯一性(这个得自己想法子)。
    在 Redis 里,保存对应的状态。
    每次内容到服务器就到 Redis 里去找这个 ID,查找对应的状态。
    momocraft
        9
    momocraft  
       Oct 4, 2020
    用 cookie 換一個一次性 token,用那個 token 連接?
    sdbybyd
        10
    sdbybyd  
    OP
       Oct 4, 2020
    @JimmyChange 这样可能有安全问题,httponly 属性就是为了前端无法读取 cookie 里面的 token,暴露这个 API 感觉不太好
    sdbybyd
        11
    sdbybyd  
    OP
       Oct 4, 2020
    @Arrowing 你这个思路就是 jwt 了,关键前端如何通过 websocket 吧这个东东发给后台
    sdbybyd
        12
    sdbybyd  
    OP
       Oct 4, 2020
    感觉还是在 beforeHandshake 这个 hook 上动手脚
    micean
        13
    micean  
       Oct 4, 2020 via Android
    ws 连接的时候也有 cookie 啊,跟 httponly 没关系吧
    既然是 httponly,说明是服务端自己管理令牌,但是换成 ws 却管理不了了?
    我不太明白……
    yc8332
        14
    yc8332  
       Oct 4, 2020
    和 http 一样啊。。websocket 本来就是基于 http 的
    yogogo
        15
    yogogo  
       Oct 4, 2020 via Android
    token 是前端请求登入的时候后端返回的,然后前端每个请求都要带上 token,websocket 一样道理
    xrr2016
        16
    xrr2016  
       Oct 4, 2020
    第一次建立 ws 链接的时候用的是普通的 http 协议,之后才是 ws
    hijoker
        17
    hijoker  
       Oct 4, 2020
    登陆,鉴权 http 服务, 返回 token,连接 ws,需要带上这个 token,后端校验 token,成功就连接,不然就断开
    pagepancn
        18
    pagepancn  
       Oct 5, 2020
    @yc8332 不对吧,websocket 是基于 socket 的吧
    abersheeran
        19
    abersheeran  
       Oct 5, 2020
    看你的客户端了。如果你客户端包含标准浏览器,那么只能走 url 参数的路子。别问,问就是浏览器标准傻逼,这个玩意他们讨论好几年也没个定论,等确定好了再等实现出来,你估计都 35 岁退休了。

    如果你客户端只是需要满足非浏览器,那简单了,websocket 握手用的 http 协议,你该咋鉴权咋鉴权。
    JimmyChange
        20
    JimmyChange  
       Oct 5, 2020 via iPhone
    @sdbybyd 有什么安全问题?又不是让你返回 JWT 的 token,返回个一次性验证 token 不就行了
    jinliming2
        21
    jinliming2  
       Oct 5, 2020
    跟 HttpOnly 有什么关系? HttpOnly 的 cookie 在 Websocket 连接的时候也是会正常发送的啊!
    刚刚在 Chrome 和 Firefox 下测试没有问题,标记为 HttpOnly 的 Cookie 在 Websocket 握手的时候都可以正常发送。

    网上搜了一下,只有 2010 年 1 月苹果的 Webkit 存在 bug 导致 HttpOnly Cookie 在 WebSocket 下不发送,但是也早已修复: https://bugs.webkit.org/show_bug.cgi?id=34289

    另外搜到一个 UC 浏览器同样的问题: https://stackoverflow.com/questions/43224033/uc-browser-not-sending-httponly-cookie-for-websocket-calls 估计也是用了那个有问题的版本的 Webkit 内核代码。
    如果确实要考虑这些使用旧版带 bug 的浏览器的用户,这个问题下也给出了参考方案:在 WebSocket 连接建立之后,若用户没有携带 Cookie,则在 Websocket 中给用户一个唯一 ID,用户拿到 ID 之后通过正常的 HTTP 带上 Cookie 请求一个 API,这样就可以将这个 Websocket 连接的 ID 与用户的 Cookie 进行绑定。加个超时自动断开连接就行。
    yc8332
        22
    yc8332  
       Oct 5, 2020
    @pagepancn 握手走的 http,只是最后协议升级而已。
    codehz
        23
    codehz  
       Oct 6, 2020
    websocket 建议不要玩 http 层的花样,有些浏览器没做好就不会发
    我这里提供一个思路,把 token 编码到 url 路径里,短期且一次性的那种(
    然后用普通 http api 去请求那个 url
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1098 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 57ms · UTC 18:21 · PVG 02:21 · LAX 11:21 · JFK 14:21
    ♥ Do have faith in what you're doing.