【问题标题】:Why cookie not being set in browser, but it does in POSTMAN?为什么 cookie 没有在浏览器中设置,但在 POSTMAN 中设置?
【发布时间】:2019-07-05 11:50:49
【问题描述】:

我正在发送一个基本身份验证的 GET 请求,服务器(后端 API)将返回(如果身份验证成功)一个 cookie。这对 POSTMAN 来说工作正常,但在浏览器中没有设置 cookie。

@GetMapping("/login")
@ResponseStatus(value=HttpStatus.OK)
public void loginUser( final HttpServletRequest request ,final HttpServletResponse response) throws UnsupportedEncodingException {

        setAuthCookieToResonse(request,response);    
    }

private void setAuthCookieToResonse(final HttpServletRequest request ,final HttpServletResponse response) throws UnsupportedEncodingException {
    logger.debug("Adding cookie after authentication");
    String cookieKey = "auth";
    String cookieValue = request.getHeader("Authorization");

    if (cookieValue != null) {
        Cookie cookie = new Cookie(cookieKey, URLEncoder.encode(cookieValue, "utf-8"));
        cookie.setHttpOnly(true);
        cookie.setDomain("localhost");

        response.addCookie(cookie);
    }
}

这是我的申请流程:

  1. 使用基本身份验证的浏览器/POSTMAN 登录。发送凭据 使用Authorization Basic xxxxxx== 标头。
  2. 服务器读取身份验证详细信息,如果正确,它会创建一个 名为 auth 的 cookie 并将其与响应(以上代码)一起发回。 对于安全层,我使用的是 Spring 安全性。
  3. 对于进一步的请求,该 cookie 将自动发送 每个请求。现在我不得不拿走那个饼干并提取 身份验证详细信息。在那之后,我不得不添加 Authorization Basic xxxxxx== 到那个请求(因为现在 Authorization 不是客户端发送的,只发送了cookie)。为了这 我创建了Filter,它将在 Spring 之前运行 BasicAuthenticationFilter.class

第 2 步适用于 POSTMAN,但不适用于浏览器。在 POSTMAN 中,服务器发送的response 包含Set-Cookie →auth=Basic xxxxxxxx=; Domain=localhost; HttpOnly

curl -i -u pu@gmail.com:password@ http://localhost:8085/api/v1/login

HTTP/1.1 200
Set-Cookie: auth=Basic xxxxxxxx==; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 0
Date: Tue, 12 Feb 2019 05:59:33 GMT

浏览器中的响应头:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:3007
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Tue, 12 Feb 2019 11:52:10 GMT
Expires: 0
Pragma: no-cache
Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

这里我需要做哪些额外的配置?

【问题讨论】:

  • 浏览器在服务器请求之前不会发送Authorization 标头。使用 POSTMAN,您可能已经告诉它先发制人地 发送标头,即服务器不请自来,所以这就是它在那里工作的原因。浏览器从服务器接收到带有WWW-Authenticate 标头的401 Unauthorized 后,将在第二个请求中发送Authorization 标头。您的服务器是否配置为这样做?
  • @Andreas 我已经添加了应用程序流程。如果还需要什么,请告诉我。
  • 您能否在浏览器中添加原始 http 响应?
  • @Ilya 已更新。请看一看。
  • 看来你没有理解我的评论。浏览器不会发送Authorization 标头,除非服务器 提示。查看浏览器请求中的标头,看看它是否真的发送了Authorization 标头。 --- 另外,当使用 BASIC 身份验证时,通常没有明确的/logon URL,因为任何 webapp URL 都可以进行登录。正常流程是:1)浏览器发送GET到/foo。 2) 服务器发送401 Unauthorized。 3) 浏览器提示用户输入密码。 4) 浏览器将 GET 重新发送到 /foo 并带有 Auth 标头。 5)服务器验证密码并处理/foo请求。

标签: java spring-boot cookies


【解决方案1】:

您必须将withCredentials 附加到您从浏览器发出的http 调用,否则浏览器将不会响应Set-Cookie 标头。

角度示例

return this.http.post(url, userLoginRequest, { withCredentials: true }) as Observable<
      LoginResponse
>

Axios 示例

axios.post(API_SERVER + '/login', { email, password }, { withCredentials: true })

XMLHttpRequest 示例

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-16
    • 2017-12-17
    • 2021-02-14
    • 2021-11-30
    • 1970-01-01
    • 2020-12-24
    • 1970-01-01
    • 2019-04-26
    相关资源
    最近更新 更多