我一直在WebSocket前阶段设置和检索cookie以识别用户。我假设一切都可以像典型的HTTP交换一样工作。
这在我测试过的所有浏览器上都运行得很完美,但报告开始在iPhone上登录,根本不会保留登录,表示 cookies未设置或发送回服务器。
// 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()
}
在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
我是否跳过允许Safari存储Cookie的某个步骤,或者这是上游 1 的问题?
P.S。我真的很想保留这种方法,因为我可以使用仅限HTTP的cookie,这主要是为了确保JavaScript无法访问它们。
答案 0 :(得分:2)
如果你的Set-Cookie
标题在其他浏览器中有效,我猜它是一个上游问题,特别是iOS Safari能够阻止cookie。默认情况下,iOS Safari会阻止第三方Cookie。
如果Cookie被阻止,则无法使用它们。如果您需要cookie,请通过在enabled=1
等登录页面上设置cookie来检测支持,然后在/ws
处理程序中检查它。如果它出现空白且Cookie被阻止,您可以尝试重定向到/please-enable-cookies
,要求用户为您的网站启用Cookie。
另一种选择是将签名的会话数据存储在本地存储中,并将其包含在Authorization
标头中的每个请求中。 https://jwt.io/
答案 1 :(得分:0)
TLDR:它是HttpOnly
标志。
看来,尽管某些浏览器允许在WebSocket连接的响应中使用Set-Cookie
标头具有HttpOnly
标志,但iOS Safari认为这种情况是“非HTTP”并阻止它。
有趣的是,虽然无法设置HttpOnly
cookie,但在连接WebSocket时会在请求标头中发送HttpOnly
cookie。这留下了一对选择:
HttpOnly
; 与RFC 6265 Storage model中概述的内容相比,我认为iOS Safari的行为不正确