如何配置 .net core 以将身份验证 cookie 发送到不同的域 [英] How to configure .net core to send authentication cookies to different domain

查看:23
本文介绍了如何配置 .net core 以将身份验证 cookie 发送到不同的域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 cookie 用于前端域与后端域不同的域.后端使用 .net core 实现,前端使用 Angular.我研究过在进行 http 调用时需要设置 withCredentials: true .但是当我将其设置为 true 时,我收到此错误:

<块引用>

对预检请求的响应未通过访问控制检查:当请求的凭据模式为包含"时,响应中Access-Control-Allow-Origin"标头的值不得为通配符*".我一直在尝试设置 CORS 和 Cookie 设置来处理这种情况.这是我来自 StartUp.cs 的相关代码.Cors 设置:

services.AddCors(options =>{options.AddPolicy("AllowDomainOrigin",建造者 =>{建设者.WithOrigins("http://some.domain.net").AllowAnyHeader().AllowAnyMethod();});options.AddPolicy("AllowForLocalhost",建造者 =>{建设者.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 = "/登录";options.LogoutPath = "/登录";}).AddCookie("localhost", options =>{options.Cookie.Domain = "localhost";options.Cookie.Name = "localhost_access_token";options.Cookie.SameSite = SameSiteMode.None;options.LoginPath = "/登录";options.LogoutPath = "/登录";}).AddCookie("othercloud", options =>{options.Cookie.Domain = "domain.com";options.Cookie.Name = "musiple_access_token";options.Cookie.SameSite = SameSiteMode.None;options.LoginPath = "/登录";options.LogoutPath = "/登录";}).AddJwtBearer(选项=>{options.TokenValidationParameters = tokenValidationParameters;});

这是我在登录控制器中登录到 HttpContext 的方法:

await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);等待 HttpContext.SignOutAsync("localhost");等待 HttpContext.SignOutAsync("othercloud");等待 HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,新的 ClaimsPrincipal(身份),auth 属性);等待 HttpContext.SignInAsync("localhost",新的 ClaimsPrincipal(身份),auth 属性);等待 HttpContext.SignInAsync("othercloud",新的 ClaimsPrincipal(身份),auth 属性);

这是我的音频文件端点:

[HttpGet("{id}")][授权(AuthenticationSchemes= CookieAuthenticationDefaults.AuthenticationScheme +", localhost, othercloud")]公共异步任务获取(int id)

如您所见,我还使用 JWT 令牌进行身份验证.我需要 cookie,因为我使用音频元素从我的 REST API 下载 mp3 文件,并且我将音频元素 src 直接设置为我的 REST API 地址.所以在使用音频元素时我无法将 JWT 设置为标头.当我的前端与后端位于同一域时,Cookie 在这种情况下运行良好,但现在我正尝试将前端也移至其他服务器和域.

如何配置后端以获取来自不同域的 cookie?

我的后端在 Azure 上.还有一些 CORS 设置,我删除了 * 并将其替换为特定地址.跟这个有关系吗?

在我找到 Azure CORS 设置后,异常更改为:

<块引用><块引用>

对预检请求的响应未通过访问控制检查:响应中Access-Control-Allow-Credentials"标头的值为",当请求的凭据模式为包含"时,该值必须为真"

编辑 2:

您需要从 Azure 中删除所有 CORS 设置以获取您的 .net 核心 cors 设置以获得 cors 控制.仍然没有成功,但可能更接近解决方案.

解决方案

我终于搞定了.正如我在编辑评论中所说,主要原因是天蓝色的 CORS 设置.在我删除它们后,我得到了我的 .net 核心设置.这是我的最终解决方案:Cookie 设置:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>{options.Cookie.Name = "access_token";options.Cookie.SameSite = SameSiteMode.None;}).AddJwtBearer(选项=>{options.TokenValidationParameters = tokenValidationParameters;});

CORS 设置:

services.AddCors(options =>{options.AddPolicy("AllowAllOrigins",建造者 =>{建设者.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials();});});...app.UseCors("AllowAllOrigins");

后台登录相关代码如下:

await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);等待 HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,新的 ClaimsPrincipal(身份),auth 属性);

这在我的音频控制器端点就足够了

[HttpGet("{id}")][授权()]公共异步任务获取(int id)

在前端,当我进行登录调用时,我设置了 withCredentials: true.

现在,当我使用 AllowAnyOrigin 而不是 WithOrigin 时,这很不安全,但由于某种原因,我没有让它与 WithOrigin 一起使用.

对于正在阅读本文并在 azure 中使用 .net Core 并希望使用 CORS 的人,请从 Azure 中删除您的 CORS 设置并在 .net core 中处理它们,因为在 .net core 中的配置比 azure 中的 CORS 多得多.以下是我从网上找到的一些内容:

I am trying to use cookies with frontend which domain is different than backend's domain. Backend is implemented with .net core and frontend is Angular. I have researched that I need to set withCredentials: true when making http calls. But when I set it to true I get this error:

Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. I have been trying to set CORS and Cookie settings to work with this situation. Here is my relevant code from StartUp.cs. Cors settings:

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 settings:

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;
            });

Here is how I login to HttpContext in login controller:

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);

And here is my endpoint for audio files:

[HttpGet("{id}")]
[Authorize(AuthenticationSchemes= CookieAuthenticationDefaults.AuthenticationScheme +", localhost, othercloud")]
public async Task<FileStreamResult> Get(int id)

So as you see I also use JWT token with authentication. I need cookies because I download mp3 file from my REST API using audio element and I'm setting audio elements src directly to my REST API address. So I can't set JWT to header when using audio element. Cookies was working well in this situation when my frontend was at same domain as backend but now I'm trying to move frontend to other server and domain as well.

How do I need to configure backend to get cookies from different domain?

My backend is on Azure. There is also some CORS settings where I remove * and replaced it with spesific address. Does this have something to do with this?

EDIT:

After I found Azure CORS settings, Exception changed to this:

Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'

EDIT 2:

You need to remove all CORS settings from Azure to get your .net core cors settings to get cors control. Still no success but maybe little closer the solution.

解决方案

Finally I got it working. As I say in my edit comment, main reason was azures CORS settings. After I remove them I get my .net core settings to hit in. Here is my final solution: Cookie settings:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => 
            {
                options.Cookie.Name = "access_token";
                options.Cookie.SameSite = SameSiteMode.None;
            })
            .AddJwtBearer(options => 
            {
                options.TokenValidationParameters = tokenValidationParameters;
            });

CORS settings:

services.AddCors(options =>
        {
            options.AddPolicy("AllowAllOrigins",
                builder =>
                {
                    builder
                        .AllowAnyOrigin()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
        });
...

app.UseCors("AllowAllOrigins");

Here is related code from login in backend:

await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
            new ClaimsPrincipal(identity),
            authProperties);

And this was enough in my audio controller endpoint

[HttpGet("{id}")]
[Authorize()]
public async Task<FileStreamResult> Get(int id)

And in frontend I set withCredentials: true when I make login call.

I now this is quite unsecure when I have AllowAnyOrigin instead of WithOrigin, but for some reason I didn't get it working with WithOrigin.

For those who are reading this and are using .net Core in azure and want use CORS remove your CORS settings from Azure and handle them in .net core because in .net core there is much more configurations than in CORS in azure. Here is some what I found from internet:

这篇关于如何配置 .net core 以将身份验证 cookie 发送到不同的域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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