浏览器未在启用 CORS 的情况下跨域跨域发送 cookie

Posted

技术标签:

【中文标题】浏览器未在启用 CORS 的情况下跨域跨域发送 cookie【英文标题】:Browser not sending cookies cross-origin cross domain with CORS enabled 【发布时间】:2019-11-05 22:41:16 【问题描述】:

我有一个 .net 核心 webapi 项目来接受像这样的跨源请求

public void ConfigureServices(IServiceCollection services)

    services.AddCors();
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);



public void Configure(IApplicationBuilder app, IHostingEnvironment env)

    if (env.IsDevelopment())
    
        app.UseDeveloperExceptionPage();
    
    else
    
        app.UseHsts();
    

    app.UseCors(opts => opts
        .WithOrigins("https://fiddle.jshell.net")
        .AllowCredentials()
        .AllowAnyMethod()
        .AllowAnyHeader());

    app.UseHttpsRedirection();
    app.UseMvc();

这有一个带有 GET 方法的值控制器

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    
        return Ok("cookies: " + string.Join(", ", HttpContext.Request.Cookies.Select(x => x.Key)));
    

现在我正尝试像这样从浏览器发送获取请求

fetch('https://api.domain.com/api/values',  
    headers: 
     
      'Content-Type': 'application/json' 
    , 
    credentials: 'include', 
    mode: 'cors'
)
.then(function(resp) 
    resp.text().then(function(data)  
        console.log(data); 
  ) 
)
.catch(function(err) 
    console.log(err) 
);

但这不会将 cookie 从页面发送到 api。我在这里想念什么?我已经尝试了所有我能找到的解决方案,包括关闭第三方 cookie

更新

所以,我仍然没有答案为什么这不起作用或任何权威来源说您不能跨域发送 cookie(或者甚至说跨域!= 跨域)。

我们发现即使来自sub-a.domian.com 的cookie 也不会发送到sub-b.domain.com。我们“解决”这个问题的方法是创建一个永久绑定到 domain.com 的 cookie,因为这些 cookie 发送到 sub-a.domain.comsub-b.domain.com

【问题讨论】:

Cookies 绑定到发布它们的域。 CORS 不会改变这一点。但是,假设不是 HttpOnly,它将允许您编写 javascript 将 cookie 从一个域复制到另一个域。 @JohnWu 其中一些是。例如,我认为您可以根据 github.com/github/fetch#sending-cookies 来做到这一点 我测试了你的代码,但它运行良好,响应包含 cookie-key 值。如果你能分享可重现的演示会更好。 @XueliChen 我很乐意,但我该怎么做呢?我是说后端。代码和我这里的一样。顺便说一句,您是否从 jsfiddle.net 网站对此进行了测试?那是我尝试过的地方。 @reggaemahn ,我根据您的代码使用 MVC 项目和 Web API 项目进行了测试。 【参考方案1】:

CORS 所做的唯一事情是让浏览器使用来自跨域请求的响应,它不会使 cookie 跨域(有关将 cookie 附加到请求的条件的更多详细信息,请参阅specification,它根本没有提到CORS)。

如果 cookie 可以通过跨域请求发送,那将是一个重大的安全漏洞,因为它会允许外部域从您自己的域中获取敏感信息,例如用户会话令牌。邪恶的开发者可以创建一个提供有用服务的 API,然后使用该 API 从网站检索大量会话令牌(可以通过 Referer 标头轻松找到原始网站)。

您使用localhost 和不同端口观察到的行为是正常的,因为端口没有考虑到cookie,这是“出于历史原因”(供参考:Are HTTP cookies port specific?)

所以留给你的选择是:

将 cookie domain 设置为父域 考虑到您的服务器可以使用标头而不是 cookie,请不要使用 cookie(例如,将 localStorage 与 javascript 和 HTTP 标头一起使用) 考虑到您已经掌握了基础设施,为 UI 和 API 使用单个域,并在服务器端进行一些 URL 重写(例如:以 /api/... 开头的传入请求被重写为本地 API URL,其他的被重写使用本地 UI URL)

【讨论】:

CORS 唯一能做的就是让浏览器使用来自跨域请求的响应。你有这方面的好资料吗? 我在回答中添加了规范 我也不同意“CORS 所做的唯一事情就是让浏览器将响应用于跨域请求”。 CORS 是管理从不同域访问 REST 服务的规范。我附上了一个指向 CORS 的 W3C 规范的链接。 w3.org/TR/cors/#user-credentials您还将看到有关如何处理 cookie 的具体措辞 向外部域发送 cookie 时,只会发送为该域设置的 cookie,不会发送来自当前域的 cookie。您不能在域之间共享 cookie,除非它们相互信任并通过专用通道进行通信,这有点 hacky:***.com/questions/3342140/cross-domain-cookies @Twistingnether 我只是希望有一些权威来源。试图理解这一点是一场噩梦。您链接到的 SO 问题有人说您可以共享 cookie,而其他人则说您不能(两者都有很多赞成票)。此外,cookie 具有 SameSiteLAXNone 的来源策略。这显然意味着应该可以将它们发送到不同的域。【参考方案2】:

浏览器未在启用 CORS 的情况下跨域跨域发送 cookie。

每个厨师都有与之关联的域,因此您可以使用 *.abc.com 并在 abc.com 和 abc.com 的所有子域上使用它 所以请确保您的 cookie 是 *.abc.com options.Cookie.Domain = ".contoso.com";

查看我的链接 sharecookies like this

services.AddCors(options =>
        
            options.AddPolicy(MyAllowSpecificOrigins,
            builder =>
            
                builder.WithOrigins("http://example.com","*.example.com"
                                    "http://www.contoso.com");
            );
        );

【讨论】:

以上是关于浏览器未在启用 CORS 的情况下跨域跨域发送 cookie的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot(十三)CORS方式实现跨域

回顾下跨域解决方案httpmiddleware

Ajax-07 基于Ajax实现跨域请求

关于cors

WeX5 - AJAX跨域调用相关知识-CORS和JSONP

浏览器跨域及其解决方案