Javascript 不会设置在 XHR 响应中收到的 httpcookie
Posted
技术标签:
【中文标题】Javascript 不会设置在 XHR 响应中收到的 httpcookie【英文标题】:Javascript won't set httpcookie received in XHR response 【发布时间】:2020-01-11 16:14:57 【问题描述】:我有一个基本的 SPA (react) API (net core 2.2) 设置,有 2 个环境:dev 和 prod(小项目)。 API
端有一个身份验证机制,用于检查每个包含 JWT 的请求中是否存在 httponly
cookie。
在开发环境中,它可以正常工作:allowCredentials()
在 API 中设置,withCredentials = true
在 React 应用程序中也设置。两者都在我的本地主机的不同端口上运行。
但在生产环境中(单独的 Heroku dynos),它不会设置 httponly
cookie:我可以使用我的凭据登录,响应标头包含带有 jwt 的 cookie,但所有其他请求我将在 request-headers 中完全不包含 cookie 标头!
然后我得到一个401 Unauthorized ...
错误(这是合乎逻辑的)。当我花了几个小时尝试所有事情时,这让我发疯了。
我的简单身份验证 XHR (vanilla) 调用:
var request = new XMLHttpRequest()
request.open('POST', apiAuthenticateUser, true)
request.setRequestHeader('Content-type', 'application/json')
request.withCredentials = true
request.send(postData)
我的Startup.cs
.net 核心 api 中的配置:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
IdentityModelEventSource.ShowPII = true;
else
app.UseHsts();
app.UseHttpsRedirection();
app.UseCors(
options => options.WithOrigins(
"https://localhost:3000",
"*productionEnvUrl*").AllowAnyMethod().AllowCredentials().AllowAnyHeader()
);
app.UseMvc(routes =>
routes.MapRoute("MainRoute", "api/controller/action");
);
app.UseAuthentication();
这就是我如何在 api 控制器操作响应中设置包含 jwt 的 httponly cookie:
Response.Cookies.Append("jwt", jwt, new CookieOptions HttpOnly = true, Secure = true );
两种环境的代码相同,只是产生不同的结果。在这两种情况下,api 都会在身份验证响应标头中向我发送正确的 cookie,但在生产环境中,我的 react 应用程序不会保留它并在其他 api 调用中将其发送回......
这是从 API 接收到的 cookie,它永远不会从 Web 应用发回:
Access-Control-Allow-Credentials :true
Access-Control-Allow-Origin :https://xxxxxxxxxx.com
Connection :keep-alive
Content-Type :application/json; charset=utf-8
Date :Mon, 09 Sep 2019 22:32:54 GMT
Server :Kestrel
Set-Cookie :jwt=xxxxxxxx; path=/; secure; samesite=lax; httponly
Transfer-Encoding :chunked
Vary :Origin
Via :1.1 vegur
如果有人有任何线索,我将永远感激不尽。
【问题讨论】:
也许您的生产服务器有一个类似于Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
的指令 - 特别是,它将所有cookie 重写为HttpOnly
?
@Crayon Violent:你的意思是它必须是安全的?
Secure
标志使它必须通过 https。 HttpOnly
使其成为只有服务器可以访问 cookie 的位置。所以例如如果您的服务器最初使用此标志写入 cookie,并且您尝试在客户端读取/写入它,它不会让您。
嗯,我从来没有听说过这个。解决办法是什么?
首先,确保是问题所在! cookie是最初由服务器设置的,是吗?打开您的浏览器开发控制台并查看 cookie 选项卡(Chrome:F12 > 应用程序 > Cookies。找到您的 cookie 条目并查看 HttpOnly
列以查看它是否已检查。(ps HttpOnly)
【参考方案1】:
原来我做错了很多事情:
我的网络应用代码一切正常。 它在开发环境中工作,因为一切都在 localhost(只是不同的端口)上运行,这是由 samesite=lax(默认值)cookie 策略授权的。 为了使其跨域,您只需指定samesite=none,然后它就可以工作。由于您失去了对 cookie 的一些控制权,因此它会产生一些潜在的漏洞,但除非您设置一些反向代理/api 网关机制,否则就 cookie(包括 httponly)而言,这是唯一的解决方法。 我对“jwt 只应存储在 httponly cookie 中”的规则感到过度兴奋:它也存在漏洞,您仍然必须确保应用程序的其余部分 xss(和其他技术)安全。如果您采取所有必要的预防措施,您可以将 jwt 安全地存储在本地存储中。感谢@Crayon Violent 抽出宝贵时间 :)
【讨论】:
以上是关于Javascript 不会设置在 XHR 响应中收到的 httpcookie的主要内容,如果未能解决你的问题,请参考以下文章
Chrome 扩展 XHR 收到 403 响应,除非从 file:/// 启动