CORS: 凭据模式为 'include'。

164

是的,我知道你在想什么——又一篇CORS问题,但这次我却被难住了。

首先,关于实际错误消息:

XMLHttpRequest无法加载http://localhost/Foo.API/token。当请求的凭证模式为'include'时,响应中的“Access-Control-Allow-Origin”头的值不能是通配符“*”。因此,来自“http://localhost:5000”的源不被允许访问。XMLHttpRequest发起的请求的凭证模式由withCredentials属性控制。

我不确定凭证模式为“include”指的是什么?

所以,当我在Postman中执行请求时,我没有遇到任何错误:

输入图像说明

但是当我通过我的angularjs Web应用程序访问相同的请求时,我被这个错误难住了。下面是我的angularjs请求/响应。如你所见,响应是OK 200,但我仍然收到CORS错误:

Fiddler请求和响应:

以下图像演示了从Web前端到API的请求和响应

Fiddler

因此,根据我在网上阅读的所有其他帖子,似乎我正在做正确的事情,这就是我无法理解这个错误的原因。最后,这里是我在angularjs中使用的代码(登录工厂):

输入图像说明

API中的CORS实现-供参考:

使用的方法1:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        EnableCrossSiteRequests(config);
    }

    private static void EnableCrossSiteRequests(HttpConfiguration config)
    {
        var cors = new EnableCorsAttribute("*", "*", "*")
        {
            SupportsCredentials = true
        };
        config.EnableCors(cors);
    }
}

使用了方法2:

public void Configuration(IAppBuilder app)
{
    HttpConfiguration config = new HttpConfiguration();
 
    ConfigureOAuth(app);
 
    WebApiConfig.Register(config);
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    app.UseWebApi(config);

}

漂亮的图片,它们是关于什么的?回答你的问题,如果包括身份验证,access-control-allow-origin响应必须是来源(浏览器页面)主机,不能是* - 因此,服务器端正在错误地执行CORS - 哦,而Postman之所以有效是因为它不是跨源请求。 - Jaromanda X
@JaromandaX,感谢您的回复。这些图片展示了请求/响应以及传递的头部,您提出问题显然说明它没有实现其目标... - Richard Bailey
最近我决定在我的Web API中放弃使用cookies,而是使用tokens。当我使用cookies时,我的CORS可以正常工作,所以我很难理解为什么服务器端没有正确实现CORS。 - Richard Bailey
1
如果您包括身份验证,那么 access-control-allow-origin 响应必须是源(浏览器页面)主机,不能是 * - Jaromanda X
这真的很不幸,考虑到在目前几乎所有主流浏览器中,在302重定向时'Origin:'头丢失。盲目地将源地址回显到响应头并不总是正确的做法。 - Umopepisdn
显示剩余6条评论
6个回答

171
该问题源自您的Angular代码:
当设置withCredentials为true时,它会尝试将凭据或cookie与请求一起发送。由于这意味着另一个来源可能正在尝试进行身份验证请求,因此通配符("*")不被允许作为"Access-Control-Allow-Origin"头部。
您必须显式地在"Access-Control-Allow-Origin"头中回复发出请求的来源才能使其工作。
我建议您明确列出要允许进行身份验证请求的来源,因为仅仅回复请求中的来源意味着任何给定的网站都可以对您的后端进行身份验证调用,如果用户恰好拥有有效会话。
我在我写的这篇文章中解释了这些内容
因此,您可以将withCredentials设置为false,或实现白名单并在涉及凭证时使用有效的来源响应CORS请求。

6
我正在开发一个使用TypeScript的Angular 5应用程序。我需要将withCredentials设置为true,否则我会收到Authorization Failed异常。如何解决这个问题:withCredentials:true。 - Ziggler
@Ziggler,我找到了解决方案,请看我的回答。 - Pavel
@mruanova,您确定请求中Access-Control-Allow-Origin头已正确设置吗?听起来好像某个地方发送了通配符。 - geekonaut
通过完全从请求中删除Access-Control-Allow-Origin来修复它,谢谢。 - mruanova
显示剩余3条评论

42

如果您正在使用CORS中间件,并且希望将withCredentials布尔值设置为true,可以像这样配置CORS:

var cors = require('cors');    
app.use(cors({credentials: true, origin: 'http://localhost:5000'}));


这正是我需要的解决方案。谢谢! - jacktim
谢谢!这就是我需要的答案。在Spring Boot中,这个注解提供了解决方案:@CrossOrigin( origins = { "http://localhost:4200", "https://www.blahblah.com" }, allowCredentials = "true" ) - Bruce Wilcox
谢谢!这就是我需要的答案。在Spring Boot中,这个注解提供了解决方案:@CrossOrigin( origins = { "http://localhost:4200", "https://www.blahblah.com" }, allowCredentials = "true" ) - undefined

12

为 Angular 5 和 Spring Security 定制 CORS(基于 Cookie 的解决方案)

在 Angular 端添加选项标志withCredentials: true以进行 Cookie 传输:

constructor(public http: HttpClient) {
}

public get(url: string = ''): Observable<any> {
    return this.http.get(url, { withCredentials: true });
}

在 Java 服务器端需要添加 CorsConfigurationSource 来配置 CORS 策略:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // This Origin header you can see that in Network tab
        configuration.setAllowedOrigins(Arrays.asList("http:/url_1", "http:/url_2")); 
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        configuration.setAllowedHeaders(Arrays.asList("content-type"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()...
    }
}

默认情况下,configure(HttpSecurity http) 方法将使用 corsConfigurationSource 来处理 http.cors()


6
如果您正在使用.NET Core,则在Startup.CS中配置CORS时,需要使用.AllowCredentials()。
在ConfigureServices内部。
services.AddCors(o => {
    o.AddPolicy("AllowSetOrigins", options =>
    {
        options.WithOrigins("https://localhost:xxxx");
        options.AllowAnyHeader();
        options.AllowAnyMethod();
        options.AllowCredentials();
    });
});

services.AddMvc();

然后在 Configure 内部:

app.UseCors("AllowSetOrigins");
app.UseMvc(routes =>
    {
        // Routing code here
    });

对我来说,造成你提到的错误的原因仅仅是缺少了options.AllowCredentials()选项。一般情况下,对于其他遇到CORS问题的人来说,顺序很重要,必须在您的Startup类中AddMVC()之前注册AddCors()。


2
对我来说,问题非常简单,我在我的 Chrome 浏览器中启用了一个名为“Allow CORS: Access-Control-Allow-Origin”的扩展程序,这个扩展程序覆盖了头部并将“Access-Control-Allow-Origin”设置为“*”,当原始响应中存在“Allow CORS: Access-Control-Allow-Origin”时。
我花了2个小时才找到它,希望能对某人有所帮助。

请提供相关扩展的截图或链接。 - Jamie Nicholl-Shelley
谢谢!但是如果用户使用这个浏览器扩展会发生什么呢?我们如何强制它对Keycloak登录没有影响? - undefined
@treecon 我觉得没有办法修复这个问题,这是插件的一个错误。 - undefined

1
如果有帮助的话,我正在使用离心机与我的ReactJS应用程序一起使用。在查看下面的一些评论后,我查看了centrifuge.js库文件,在我的版本中,它具有以下代码片段:
if ('withCredentials' in xhr) {
 xhr.withCredentials = true;
}

我移除了这三行代码后,应用程序正常工作,符合预期。

希望能对您有所帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接