【问题标题】:Cannot set cookie in client from a Go API无法从 Go API 在客户端中设置 cookie
【发布时间】:2022-01-11 19:39:04
【问题描述】:

我有一个用 Go 编写的后端,托管在 Heroku 上,我们称之为 https://foo.herokuapp.com。我有一个托管在不同域上的前端,我们称之为https://ui.example.com。 后端 API 有一个端点 /api/user/login,它以 cookie 的形式发回一个 JSON Web Token,如下所示:

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 不存在于应用程序选项卡(或存在 cookie 的 Firefox 中的存储选项卡)中。浏览器没有保存 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))

但这是行不通的。

我阅读了许多主题/博客。到目前为止没有任何效果。我做错了什么?

【问题讨论】:

  • 这不能解决您的问题,但time.Hour 是一小时内的纳秒数(不是秒数)! Cookie.MaxAge 应该是秒数,所以应该是:MaxAge: int(time.Hour.Seconds() * 24 * 3)
  • 另外:设置 MaxAge xor Expires(首选 MaxAge)。
  • @icza 不错,谢谢!
  • @Volker 是的,我读到 MaxAge 现在应该是首选。我添加了两者,因为我最初不确定。

标签: http go heroku cookies jwt


【解决方案1】:

Cookies 由浏览器为最初设置 cookie 的域保存。只是因为您在“应用程序”选项卡中看不到 cookie,并不意味着 cookie 没有保存。

如果您的前端 https://ui.example.com 对 https://foo.herokuapp.com 进行 XHR 调用,并且该调用返回 Set-Cookie 标头,则浏览器将该 cookie 保存在 foo.herokuapp.com 域下。您不会在ui.example.com 的应用程序选项卡中看到它。不过,当您再次对 foo.herokuapp.com 进行 XHR 调用时,浏览器将发送您之前设置的 cookie。

您可以进行此实验:登录后,打开一个新选项卡并导航至https://foo.herokuapp.com。现在打开“应用程序”选项卡,您应该会在那里看到您的 cookie。

也就是说,请记住,浏览器会将这些 cookie 视为 3rd 方 cookie,并且浏览器供应商最终将放弃对 3rd 方 cookie 的支持。最终,您应该确保您的前端和后端来自同一个父域。

至于另一个问题 - Heroku 在其网关和您的应用程序之间终止 SSL 不是问题。 cookie 上的secure 标志是浏览器的信息 - 浏览器不会通过非 SSL 连接接受或发送带有此标志的 cookie。您的浏览器和 heroku 服务器之间的连接是 SSL,因此 cookie 将被接受/发送。在您的后端,cookie 只是 HTTP 标头,后端并不真正关心 cookie 的标志或连接类型。

【讨论】:

  • 哇,您对实验的看法是正确的。是的,我正在将两者放在同一个域上,并且它正在按预期工作。谢谢!
猜你喜欢
  • 1970-01-01
  • 2014-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-29
  • 1970-01-01
  • 2020-10-21
  • 2015-01-28
相关资源
最近更新 更多