如何配置 .net 核心以将身份验证 cookie 发送到不同的域
Posted
技术标签:
【中文标题】如何配置 .net 核心以将身份验证 cookie 发送到不同的域【英文标题】:How to configure .net core to send authentication cookies to different domain 【发布时间】:2018-08-19 12:10:04 【问题描述】:我正在尝试将 cookie 用于前端的域与后端的域不同。后端是用 .net 核心实现的,前端是 Angular。 我研究过在进行 http 调用时需要设置 withCredentials: true 。但是当我将它设置为 true 时,我得到了这个错误:
对预检请求的响应未通过访问控制检查:当请求的凭据模式为“包含”时,响应中的“Access-Control-Allow-Origin”标头的值不得为通配符“*”。 我一直在尝试设置 CORS 和 Cookie 设置以应对这种情况。这是我来自 StartUp.cs 的相关代码。 Cors 设置:
services.AddCors(options =>
options.AddPolicy("AllowDomainOrigin",
builder =>
builder
.WithOrigins("http://some.domain.net")
.AllowAnyHeader()
.AllowAnyMethod();
);
options.AddPolicy("AllowForLocalhost",
builder =>
builder
.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
);
);
services.AddSession(options =>
options.Cookie.SameSite = SameSiteMode.None;
);
...
app.UseCors("AllowDomainOrigin");
app.UseCors("AllowForLocalhost");
Cookie 设置:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
options.Cookie.Domain = "some.domain.net";
options.Cookie.Name = "access_token";
options.Cookie.SameSite = SameSiteMode.None;
options.LoginPath = "/login";
options.LogoutPath = "/login";
)
.AddCookie("localhost", options =>
options.Cookie.Domain = "localhost";
options.Cookie.Name = "localhost_access_token";
options.Cookie.SameSite = SameSiteMode.None;
options.LoginPath = "/login";
options.LogoutPath = "/login";
)
.AddCookie("othercloud", options =>
options.Cookie.Domain = "domain.com";
options.Cookie.Name = "musiple_access_token";
options.Cookie.SameSite = SameSiteMode.None;
options.LoginPath = "/login";
options.LogoutPath = "/login";
)
.AddJwtBearer(options =>
options.TokenValidationParameters = tokenValidationParameters;
);
这是我在登录控制器中登录 HttpContext 的方式:
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync("localhost");
await HttpContext.SignOutAsync("othercloud");
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(identity),
authProperties);
await HttpContext.SignInAsync("localhost",
new ClaimsPrincipal(identity),
authProperties);
await HttpContext.SignInAsync("othercloud",
new ClaimsPrincipal(identity),
authProperties);
这是我的音频文件端点:
[HttpGet("id")]
[Authorize(AuthenticationSchemes= CookieAuthenticationDefaults.AuthenticationScheme +", localhost, othercloud")]
public async Task<FileStreamResult> Get(int id)
如您所见,我还将 JWT 令牌用于身份验证。我需要 cookie,因为我使用音频元素从我的 REST API 下载 mp3 文件,并且我将音频元素 src 直接设置为我的 REST API 地址。所以我不能在使用音频元素时将 JWT 设置为标题。当我的前端与后端位于同一域时,Cookies 在这种情况下运行良好,但现在我正尝试将前端移动到其他服务器和域。
我需要如何配置后端以获取来自不同域的 cookie?
我的后端在 Azure 上。还有一些 CORS 设置,我删除 * 并将其替换为特定地址。跟这个有关系吗?
编辑:
在我找到 Azure CORS 设置后,异常更改为:
对预检请求的响应未通过访问控制检查:响应中“Access-Control-Allow-Credentials”标头的值为“”,当请求的凭据模式为“包含”时,该值必须为“真”
编辑 2:
您需要从 Azure 中删除所有 CORS 设置以获取您的 .net 核心 cors 设置以获取 cors 控制权。仍然没有成功,但可能更接近解决方案。
【问题讨论】:
【参考方案1】:我终于让它工作了。正如我在编辑评论中所说,主要原因是天蓝色 CORS 设置。删除它们后,我可以使用 .net 核心设置。这是我的最终解决方案: Cookie 设置:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
options.Cookie.Name = "access_token";
options.Cookie.SameSite = SameSiteMode.None;
)
.AddJwtBearer(options =>
options.TokenValidationParameters = tokenValidationParameters;
);
CORS 设置:
services.AddCors(options =>
options.AddPolicy("AllowAllOrigins",
builder =>
builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
);
);
...
app.UseCors("AllowAllOrigins");
这是后台登录的相关代码:
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(identity),
authProperties);
这在我的音频控制器端点就足够了
[HttpGet("id")]
[Authorize()]
public async Task<FileStreamResult> Get(int id)
在我进行登录调用时,我在前端设置了 withCredentials: true。
现在,当我使用 AllowAnyOrigin 而不是 WithOrigin 时,这是非常不安全的,但由于某种原因,我没有让它与 WithOrigin 一起使用。
对于正在阅读本文并在 azure 中使用 .net Core 并希望使用 CORS 的用户,请从 Azure 中删除您的 CORS 设置并在 .net core 中处理它们,因为在 .net core 中的配置比 azure 中的 CORS 多得多。以下是我从网上找到的一些资料:
https://feedback.azure.com/forums/169385-web-apps/suggestions/32371078-access-control-allow-credentials-not-set-in-creden https://github.com/Azure/azure-functions-host/issues/620 最后一个是有人使用 Azure 函数设置标头的链接,但是当我使用 .net 核心时,我发现这是完全错误的。【讨论】:
以上是关于如何配置 .net 核心以将身份验证 cookie 发送到不同的域的主要内容,如果未能解决你的问题,请参考以下文章
如何同步表单身份验证 cookie 和 Asp.Net 会话的生命周期?
.Net SignalR 在还配置了 Cookie 身份验证时使用 JWT 承载身份验证