Cookies无法在Apple设备上的WebSocket上运行

tra*_*r09 5 cookies safari websocket ios

在WebSocket之前的阶段中,我一直在设置和检索Cookie以识别用户。我以为一切都可以通过典型的HTTP交换工作。

这在我测试过的所有浏览器上都可以正常使用,但是有报道说,在iPhone上根本不会保留登录,这表明未设置cookie或将cookie发送回服务器

// fret not, safety checks removed for brevity

const (
    sessionKeyCookieName string = "session-key"
    webSocketPath        string = "/ws"
)

func serveWs(w http.ResponseWriter, r *http.Request) {
    var sessionKey [sha1.Size]byte
    var u *user
    for _, cookie := range r.Cookies() {
        if cookie.Name != sessionKeyCookieName {
            continue
        }
        slice, err := base64.StdEncoding.DecodeString(cookie.Value)
        if err != nil {
            continue
        } else {
            copy(sessionKey[:], slice)
        }
    }
    u, _ = getUserBySessionKey(sessionKey)

    // regenerate key. TODO: does that add security?
    rand.Read(sessionKey[:])

    header := make(http.Header)
    header.Add("Set-Cookie", (&http.Cookie{
        Name:     sessionKeyCookieName,
        Value:    base64.StdEncoding.EncodeToString(sessionKey[:]),
        MaxAge:   int(sessionLength.Seconds()),
        HttpOnly: true,
        Domain:   strings.SplitN(r.Host, ":", 2)[0],
    }).String())

    ws, err := upgrader.Upgrade(w, r, header)
    if err != nil {
        if _, ok := err.(websocket.HandshakeError); !ok {
            log.Println(err)
        }
        return
    }

    // do things to `user` so their messages go to where they're needed

    go c.writePump()
    c.readPump()
}
Run Code Online (Sandbox Code Playgroud)

Firefox网络开发工具上显示的标题

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: eSazcZyZKj2dfa2UWSY+a4wThC8=
Access-Control-Allow-Origin: *
Set-Cookie: session-key=RNStK2z2gAsan7DyNKQ+efjyr7c=; Domain=redacted.org; Max-Age=259200; HttpOnly
Run Code Online (Sandbox Code Playgroud)

我是否跳过了允许Safari存储cookie的步骤,或者这是上游的问题1

PS我真的很想保留这种方法,因为我可以使用仅HTTP的cookie,并且大多数情况下可以确保JavaScript无法访问它们。


  1. 加里看起来也有类似的问题。简而言之,Cookie不会通过WebSockets返回。

tra*_*r09 5

TLDR:这是HttpOnly旗帜。


看起来,虽然某些浏览器确实允许Set-CookieWebSocket 连接响应中的标头具有HttpOnly标志,但 iOS Safari 将这种情况视为“非 HTTP”并阻止它。

有趣的是,虽然HttpOnly无法设置cookie ,但HttpOnly在连接 WebSocket 时,cookie 会在请求标头中发送。这留下了一对选项:

  • 增加风险而忽略HttpOnly
  • 使用另一个普通 HTTP 请求设置 cookie,很可能是一个甚至没有响应正文的请求。

RFC 6265 存储模型中概述的相比,我认为 iOS Safari 的行为是不正确的