Cookie无法在JavaScript(和开发工具)中访问,但会与XHR请求一起发送(不使用httponly) [英] Cookies are not accessible within JavaScript (and the dev tools) but sent along with XHR request (no httponly used)

查看:91
本文介绍了Cookie无法在JavaScript(和开发工具)中访问,但会与XHR请求一起发送(不使用httponly)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在具有基于会话授权的不同域上同时使用前端和后端应用程序.我已经设置了一个有效的CORS配置,该配置可以在localhost上正常运行(例如,从端口:9000到端口:8080).一旦将应用程序部署到安全域(两个域都只允许HTTPS)上,就无法在JavaScript中访问CSRF cookie,从而导致前端的后续请求不正确(缺少CSRF标头).

cookie由后端在Set-Cookie标头中设置,不使用,使用HttpOnly标志设置.它实际上是在浏览器中的某个地方设置的,因为后续请求包含会话cookie和CSRF cookie.尝试通过JavaScript(例如在控制台中使用document.cookie)访问它返回一个空字符串. Chrome的DevTools不在前端域上显示任何 cookie(甚至没有列出后端域).

我期望cookie被设置并在当前域(前端域)上可见.我正在使用 axios 库的withCredentials标志.

您有什么想法,为什么无法从JavaScript或Chrome中的DevTools访问cookie?这与Strict-Transport-Security标头有什么关系?


标题

1.初始GET响应标头

 HTTP/1.1 401 Unauthorized
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://[my-frontend-domain]
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Encoding: gzip
Content-Type: application/json;charset=UTF-8
Date: Wed, 20 Sep 2017 11:57:07 GMT
Expires: 0
Pragma: no-cache
Server: Apache-Coyote/1.1
Set-Cookie: CSRF-TOKEN=[some-token]; Path=/
Vary: Origin,Accept-Encoding
X-Content-Type-Options: nosniff
X-Vcap-Request-Id: [some-token]
X-Xss-Protection: 1; mode=block
Content-Length: [some-length]
Strict-Transport-Security: max-age=15768000; includeSubDomains 

2.后续POST请求标头

 POST /api/authentication HTTP/1.1
Host: [my-backend-host]
Connection: keep-alive
Content-Length: [some-length]
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: [my-frontend-host]
User-Agent: [Google-Chrome-User-Agent]
Content-Type: application/x-www-form-urlencoded
DNT: 1
Referer: [my-frontend-host]
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,de-CH;q=0.2,it;q=0.2
Cookie: [some-other-cookies]; CSRF-TOKEN=[same-token-as-in-the-previous-request] 

此请求应包含CSRF标头,如果可通过JavaScript访问cookie,则会自动添加该标头.

解决方案

简而言之,不可能访问跨域cookie,document.cookie只能访问当前(

从本地主机部署(仅将后端服务器和前端服务器仅使用不同的端口)切换到使用两个不同主机的端口时,很容易犯此错误.这将在本地工作,因为cookie在端口之间共享,并且在使用两个不同的主机时将失败. (与其他CORS问题不同,这些问题也将在本地公开)

有关更多信息和解决方法,请参见 ssc-hrep3的答案.

I'm using both a front-end and a back-end application on a different domain with a session-based authorization. I have setup a working CORS configuration, which works as expected on localhost (e.g. from port :9000 to port :8080). As soon as I deploy the applications on secure domains (both domains only allow HTTPS), the CSRF cookie is not accessible anymore within JavaScript, leading to an incorrect follow-up request of the front-end (missing the CSRF header).

The cookie is set by the back-end in the Set-Cookie header without using the HttpOnly flag. It is actually set somewhere in the browser, because the follow-up request contains both the session cookie and the CSRF cookie. Trying to access it by JavaScript (using e.g. document.cookie in the console) returns an empty string. The DevTools of Chrome do not show any cookies on the front-end domain (the back-end domain is not even listed).

I'm expecting the cookie to be set and being visible on the current domain (front-end domain). I'm using the withCredentials flag of the axios library.

Do you have any idea, why the cookie cannot be accessed from JavaScript nor from the DevTools in Chrome? Does this have anything to do with the Strict-Transport-Security header?


Headers

1. Initial GET Response Header

HTTP/1.1 401 Unauthorized
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://[my-frontend-domain]
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Encoding: gzip
Content-Type: application/json;charset=UTF-8
Date: Wed, 20 Sep 2017 11:57:07 GMT
Expires: 0
Pragma: no-cache
Server: Apache-Coyote/1.1
Set-Cookie: CSRF-TOKEN=[some-token]; Path=/
Vary: Origin,Accept-Encoding
X-Content-Type-Options: nosniff
X-Vcap-Request-Id: [some-token]
X-Xss-Protection: 1; mode=block
Content-Length: [some-length]
Strict-Transport-Security: max-age=15768000; includeSubDomains

2. Follow-up POST Request Header

POST /api/authentication HTTP/1.1
Host: [my-backend-host]
Connection: keep-alive
Content-Length: [some-length]
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: [my-frontend-host]
User-Agent: [Google-Chrome-User-Agent]
Content-Type: application/x-www-form-urlencoded
DNT: 1
Referer: [my-frontend-host]
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4,de-CH;q=0.2,it;q=0.2
Cookie: [some-other-cookies]; CSRF-TOKEN=[same-token-as-in-the-previous-request]

This request should contain a CSRF header which would automatically be added if the cookie was accessible with JavaScript.

解决方案

In short, it is not possible to access cross-origin cookies, document.cookie can only access the current (or parent) domain cookies.

The hint for that being the root cause, was ssc-hrep3 mentioning "both domains" in his question.

It's very to easy to make that mistake when switching from a localhost deployment, using only different ports for back-end and front-end servers, to one that uses two different hosts. That will work locally, because cookies are shared across ports, and will fail when two different hosts are used. (Unlike some other CORS issues that will be also exposed locally)

See ssc-hrep3's answer for more information and a workaround.

这篇关于Cookie无法在JavaScript(和开发工具)中访问,但会与XHR请求一起发送(不使用httponly)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆