未在浏览器中创建响应标头中的 Set-Cookie - 使用 http POST
Posted
技术标签:
【中文标题】未在浏览器中创建响应标头中的 Set-Cookie - 使用 http POST【英文标题】:Set-Cookie in Response Header not being created in browser - Using http POST 【发布时间】:2022-02-16 22:30:19 【问题描述】:我一直被与 cookie 相关的此类问题所困扰。
我的情况是这样的:
我的后端在服务器上 (localhst:12456) 我的 Angular 2 应用程序在另一台服务器 (localhost:5555) 上运行我的后端只是一个 ASP.NET 应用程序,我正在尝试从 apiController 对用户进行身份验证。 api Controller 是这样的:
[System.Web.Mvc.HttpPost]
public HttpResponseMessage HandleLogin([FromBody] LoginModel loginModel)
if (!String.IsNullOrEmpty(loginModel.Username) && !String.IsNullOrEmpty(loginModel.Password))
if (Members.Login(loginModel.Username, loginModel.Password))
var resp = Request.CreateResponse<UserAuthenticationModel>(
HttpStatusCode.OK,
new UserAuthenticationModel() IsAuthenticated = true
);
//create and set cookie in response
var cookie = new CookieHeaderValue("customCookie", "cookieVal");
cookie.Expires = DateTimeOffset.Now.AddDays(1);
cookie.Domain = Request.RequestUri.Host;
cookie.Path = "/";
resp.Headers.AddCookies(new CookieHeaderValue[] cookie );
return resp;
return Request.CreateResponse<UserAuthenticationModel>(
new UserAuthenticationModel() IsAuthenticated = false
);
现在,在我的 Angular 应用中,我正在调用一个 http 帖子:
headers.append('Access-Control-Allow-Credentials', true);
return this._http.post(this._globalVariables.BACKEND_API_HANDLE_LOGIN, loginModel, headers: headers)
.map((response : Response) => response);
this._loginService.getLoginModel() 。订阅( loginModel => this._signInPageModel = loginModel, 错误 => 控制台日志(错误) ); 现在,在我的 api 控制器方法(HandleLogin)中,我有一个测试 cookie 和另一个用于 FormsAuthentication 的 cookie,当用户成功登录并返回到我的 Angular 应用程序时,不会创建任何 cookie。
现在,可以看到 cookie 以及我的响应标头的帖子:
我对此感到很困惑,并感谢任何帮助以成功获得登录过程。
提前谢谢你。
【问题讨论】:
你还有什么问题? 你找到问题了吗? 【参考方案1】:我在同一个问题上浪费了一整天。我发现这些是重要的部分:
1.您需要在服务器上添加以下标头(替换为您的客户端主机地址)。 CORS 需要这些,因为您的两个站点使用不同的端口号。
Access-Control-Allow-Origin: http://localhost:5555
Access-Control-Allow-Credentials: true
对于 WebAPI,这意味着将以下内容放在 WebApiConfig.Register
的顶部:
var cors = new EnableCorsAttribute("http://localhost:5555", "*", "GET,POST");
cors.SupportsCredentials = true;
config.EnableCors(cors);
2。准确说明您如何设置 Cookie
看看这些:
response.Headers.AddCookies(new CookieHeaderValue[]
new CookieHeaderValue("WorkingCookie", cookieValue) Path="/" ,
new CookieHeaderValue("NotWorkingCookie", cookieValue)
);
如果不指定路径,我无法让 CORS cookie 工作。此外,this SO answer 声称在生产环境中,您还需要指定域。我还没到那里,所以我现在只是记下它。
3.注意后端限制
据我所知,Web API 并不是真正的问题,但对于 php,多个 Set-Cookie
标头无法正常工作。我只能将列出的最后一个保留在客户端上。
4.在您的 HTTP 请求上使用 withCredentials*
这是我对您前面列出的电话的看法:
return this._http.post(this._globalVariables.BACKEND_API_HANDLE_LOGIN,
loginModel, headers: headers, withCredentials: true)
.map((response : Response) => response);
注意 withCredentials
作为选项的一部分传递。
这是您缺少的部分,绝对是关键。其他步骤是为了确保 cookie 由服务器正确发送并由浏览器持久保存,但 withCredentials
管理 whether the browser will include its cookies in the request header。
不过,您需要确保使用的是更新版本的 Angular;甚至一些 RC 版本完全忽略了withCredentials
选项,因此根本不能用于像这样的 CORS 调用。
最后说明 如果您要使用 cookie 创建 CORS 身份验证系统,则需要注意两件事:
-
在 Web API 中标记您的会话 cookie
HttpOnly
,这样它就不会被注入的 javascript 篡改。
在服务器端生成并存储一个密钥,您在名为XSRF-TOKEN
的(非HttpOnly
)cookie 中返回该密钥。在每次 API 调用中,将此存储的值与 Angular 将返回的 X-XSRF-TOKEN
标头的值进行比较。这是防止CSRF attacks 所必需的。
【讨论】:
以上是关于未在浏览器中创建响应标头中的 Set-Cookie - 使用 http POST的主要内容,如果未能解决你的问题,请参考以下文章
即使响应包含 ajax 请求的“Set-Cookie”标头,cookie 也不会存储在浏览器中
即使响应包含ajax请求的“Set-Cookie”标头,cookie也不会存储在浏览器中
如果我们尝试设置之前安全的 cookie,浏览器会忽略 Set-Cookie 响应标头
在 AWS Cloudfront 源请求中返回带有 set-cookie 标头的响应