无法通过 Go 在客户端中设置 cookie API
Cannot set cookie in client from a Go API
我有一个用 Go 编写的后端,托管在 Heroku 上,我们称它为 https://foo.herokuapp.com
。我有一个托管在不同域上的前端,我们称它为 https://ui.example.com
。
后端 API 有一个端点 /api/user/login
,它以 cookie 的形式发回 JSON Web 令牌,如下所示:
http.SetCookie(w, &http.Cookie{
Name: "token",
Value: token, // the JWT
HttpOnly: false, // for testing, set to true later once I fix this
MaxAge: int(time.Hour * 24 * 3),
Expires: time.Now().UTC().Add(time.Hour * 24 * 3),
Path: "/",
Secure: true,
SameSite: http.SameSiteNoneMode,
})
这些是我在服务器上的 CORS 设置。
crossOrigin := cors.New(cors.Options{
AllowedOrigins: []string{allowedOrigin},
AllowCredentials: true,
AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodPut},
})
前端向后端发出如下请求。
const endpoint = "/api/user/login/"
fetch(host + endpoint, {
method: "POST",
credentials: 'include',
body: JSON.stringify({
email,
password
})
}).then((response) => console.log(response))
.catch((err) => console.log(err));
问题:
现在这个 cookie 实际上在我浏览器的网络选项卡中可见。
但应用程序选项卡中不存在该 cookie(或 firefox 中存在 cookie 的存储选项卡)。浏览器未保存 cookie,这导致后续请求失败,因为 cookie 中的令牌在处理实际请求之前已被验证和解码。
在另一个有点相关的线程中,我了解到 Heroku 在到达我的应用程序之前终止了 SSL。因此,不能为非 SSL 流量设置安全 cookie。那里的解决方案建议信任 X-Forwarded-For
中找到的方案。我使用 https://github.com/gorilla/handlers 包启用了它,如下所示。
// srv is my actual handler
// crossOrigin is the CORS middleware
// finally wrapped by ProxyHeaders middleware
handlers.ProxyHeaders(crossOrigin.Handler(srv))
但这不起作用。
我读了很多threads/blogs。到目前为止没有任何效果。我做错了什么?
Cookie 由浏览器为最初设置 cookie 的域保存。只是因为您在“应用程序”选项卡中看不到 cookie,并不意味着没有保存 cookie。
如果您的前端 https://ui.example.com
对 https://foo.herokuapp.com
进行 XHR 调用并调用 returns a Set-Cookie
header,则浏览器将该 cookie 保存在foo.herokuapp.com
域。您不会在 ui.example.com
的应用程序选项卡中看到它。不过,当您对 foo.herokuapp.com
进行另一个 XHR 调用时,浏览器将发送您之前设置的 cookie。
你可以做这个实验:登录后,打开一个新标签并导航到 https://foo.herokuapp.com
。现在打开“应用程序”选项卡,您应该会在那里看到您的 cookie。
也就是说,请记住,浏览器会将这些 cookie 视为第 3 方 cookie,浏览器供应商最终会放弃对第 3 方 cookie 的支持。最后,您应该确保您的前端和后端是从同一个 parent 域提供服务的。
至于另一个问题 - Heroku 在其网关和您的应用程序之间终止 SSL 不是问题。 cookie 上的 secure
标志是浏览器的信息 - 浏览器不会通过 non-SSL 连接接受或发送带有此标志的 cookie。您的浏览器和 heroku 服务器之间的连接是 SSL,因此 cookie 将为 accepted/sent。在您的后端,cookie 只是 HTTP headers,后端并不真正关心 cookie 的标志或连接类型。
我有一个用 Go 编写的后端,托管在 Heroku 上,我们称它为 https://foo.herokuapp.com
。我有一个托管在不同域上的前端,我们称它为 https://ui.example.com
。
后端 API 有一个端点 /api/user/login
,它以 cookie 的形式发回 JSON Web 令牌,如下所示:
http.SetCookie(w, &http.Cookie{
Name: "token",
Value: token, // the JWT
HttpOnly: false, // for testing, set to true later once I fix this
MaxAge: int(time.Hour * 24 * 3),
Expires: time.Now().UTC().Add(time.Hour * 24 * 3),
Path: "/",
Secure: true,
SameSite: http.SameSiteNoneMode,
})
这些是我在服务器上的 CORS 设置。
crossOrigin := cors.New(cors.Options{
AllowedOrigins: []string{allowedOrigin},
AllowCredentials: true,
AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodPut},
})
前端向后端发出如下请求。
const endpoint = "/api/user/login/"
fetch(host + endpoint, {
method: "POST",
credentials: 'include',
body: JSON.stringify({
email,
password
})
}).then((response) => console.log(response))
.catch((err) => console.log(err));
问题:
现在这个 cookie 实际上在我浏览器的网络选项卡中可见。
但应用程序选项卡中不存在该 cookie(或 firefox 中存在 cookie 的存储选项卡)。浏览器未保存 cookie,这导致后续请求失败,因为 cookie 中的令牌在处理实际请求之前已被验证和解码。
在另一个有点相关的线程中,我了解到 Heroku 在到达我的应用程序之前终止了 SSL。因此,不能为非 SSL 流量设置安全 cookie。那里的解决方案建议信任 X-Forwarded-For
中找到的方案。我使用 https://github.com/gorilla/handlers 包启用了它,如下所示。
// srv is my actual handler
// crossOrigin is the CORS middleware
// finally wrapped by ProxyHeaders middleware
handlers.ProxyHeaders(crossOrigin.Handler(srv))
但这不起作用。
我读了很多threads/blogs。到目前为止没有任何效果。我做错了什么?
Cookie 由浏览器为最初设置 cookie 的域保存。只是因为您在“应用程序”选项卡中看不到 cookie,并不意味着没有保存 cookie。
如果您的前端 https://ui.example.com
对 https://foo.herokuapp.com
进行 XHR 调用并调用 returns a Set-Cookie
header,则浏览器将该 cookie 保存在foo.herokuapp.com
域。您不会在 ui.example.com
的应用程序选项卡中看到它。不过,当您对 foo.herokuapp.com
进行另一个 XHR 调用时,浏览器将发送您之前设置的 cookie。
你可以做这个实验:登录后,打开一个新标签并导航到 https://foo.herokuapp.com
。现在打开“应用程序”选项卡,您应该会在那里看到您的 cookie。
也就是说,请记住,浏览器会将这些 cookie 视为第 3 方 cookie,浏览器供应商最终会放弃对第 3 方 cookie 的支持。最后,您应该确保您的前端和后端是从同一个 parent 域提供服务的。
至于另一个问题 - Heroku 在其网关和您的应用程序之间终止 SSL 不是问题。 cookie 上的 secure
标志是浏览器的信息 - 浏览器不会通过 non-SSL 连接接受或发送带有此标志的 cookie。您的浏览器和 heroku 服务器之间的连接是 SSL,因此 cookie 将为 accepted/sent。在您的后端,cookie 只是 HTTP headers,后端并不真正关心 cookie 的标志或连接类型。