简体   繁体   English

CORS 策略不想与 SignalR 和 ASP.NET 核心一起使用

[英]CORS policy don't want to work with SignalR and ASP.NET core

I have a problem with my ASP.NET core API and my Angular Client.我的 ASP.NET 核心 API 和 Angular 客户端有问题。 I want to implement SignalR to have a connection between API and Angular.我想实现 SignalR 以在 API 和 Angular 之间建立连接。 The cors policy are already activated on our client and the API because we can already retrieve data from the API with our client. cors 策略已经在我们的客户端和 API 上激活,因为我们已经可以使用我们的客户端从 API 检索数据。 But the problem now is when I try to use SignalR I receive an error with CORS POLICY:但现在的问题是,当我尝试使用 SignalR 时,收到 CORS 策略错误:

Access to XMLHttpRequest at ' http://localhost:50501/CoordinatorHub/negotiate ' from origin ' http://localhost:4200 ' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.从源“ http://localhost:4200 ”访问“ http://localhost:50501/CoordinatorHub/negotiate ”的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:无“访问” -Control-Allow-Origin' 标头存在于请求的资源上。

But there's already cors policy inside the Startup.cs on our API and it's like that:但是我们 API 的 Startup.cs 中已经有 cors 策略,就像这样:

In the ConfigureServices method :在 ConfigureServices 方法中:

services.AddCors(options =>
{
    options.AddPolicy("AllowSpecificOrigin",
        builder => 
        builder.WithOrigins("http://localhost:4200/")
            .AllowCredentials()
            //.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .SetIsOriginAllowedToAllowWildcardSubdomains());
});

And inside the Configure method :在 Configure 方法中:

app.UseCors("AllowSpecificOrigin");

In our Client we just want to try to make a connection between the API and the client and it's like that:在我们的客户端中,我们只想尝试在 API 和客户端之间建立连接,就像这样:

this.hubConnection.start({withCredentials: false}).then(() => 
     this.hubConnection.invoke('send', 'Hello'));

Note this can be applied to .net core 3.1请注意,这可以应用于 .net core 3.1

As it's stated on microsoft docs it seems doesn't work docs正如它在 microsoft docs 上所说,它似乎不起作用docs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // Preceding code ommitted.
    app.UseRouting();

    app.UseCors();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    // Following code ommited.
}

Warning警告

With endpoint routing, the CORS middleware must be configured to execute between the calls to UseRouting and UseEndpoints.对于端点路由,必须将 CORS 中间件配置为在对 UseRouting 和 UseEndpoints 的调用之间执行。 Incorrect configuration will cause the middleware to stop functioning correctly.不正确的配置将导致中间件停止正常运行。

But if you move your UseCors() in the first place your application will work as expected so the working code will be但是,如果您首先移动 UseCors(),您的应用程序将按预期工作,因此工作代码将是

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
                options.AddDefaultPolicy(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()));
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//place your useCors here 
    app.UseCors();
    app.UseRouting();


    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    // Following code ommited.
}

The accepted answer did not work for me so I decided to put down here what worked for me.接受的答案对我不起作用,所以我决定把对我有用的东西放在这里。 In case someone stumbles across the same issue.万一有人偶然发现同样的问题。

I was facing same issue in my local testing while playing around with signalR on Angular 9.在 Angular 9 上使用 signalR 时,我在本地测试中遇到了同样的问题。

I solved it by switching my Asp NET Core (3.1) app URL from https to http.我通过将我的 Asp NET Core (3.1) 应用 URL 从 https 切换到 http 来解决它。 if you are using Visual Studio,如果您使用的是 Visual Studio,

  1. just right click on project properties -> Debug.只需右键单击项目属性-> 调试。
  2. Uncheck Enable SSL取消选中启用 SSL

Asp网络核心项目

Also do not forget to change the port on your URL in angular App.也不要忘记在 angular App 中更改 URL 上的端口。 So basically URL in angular app will be something like this所以基本上角度应用程序中的 URL 将是这样的

this.hubConnection = new signalR.HubConnectionBuilder()
      .withUrl("http://localhost:50782/hub").build();

whereas the relevant code in Configure method is something like this而配置方法中的相关代码是这样的

app.UseHttpsRedirection();
app.UseStaticFiles();

   
app.UseRouting();
app.UseCors("_myAllowSpecificOrigins");

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
    endpoints.MapHub<ChatHub>("/hub");
});

and in your configureServices method I had following在你的 configureServices 方法中,我遵循了

    services.AddRazorPages();

    services.AddCors(options =>
        {
            options.AddPolicy("_myAllowSpecificOrigins",
                builder =>
                {
                    builder.WithOrigins("https://localhost:4200")
                           .AllowAnyHeader()
                           .AllowAnyMethod()
                           .SetIsOriginAllowed((x) => true)
                           .AllowCredentials();
                });
        });
    
   services.AddSignalR();

Hope this helps !希望这可以帮助 !

UPDATE更新

if you are just playing around with samples on your local machine you can also try to run chrome in security mode as mentioned here如果你只是玩弄你的本地计算机上的样品,你也可以尝试运行安全模式铬提到这里

on my mac I just simply ran command from terminal在我的 Mac 上,我只是简单地从终端运行命令

open -n -a /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir="/tmp/chrome_dev_test" --disable-web-security

With this you should be able to run your sample without CORS bothering有了这个,您应该能够在没有 CORS 打扰的情况下运行您的示例

I solved my problem according to this link我根据这个链接解决了我的问题

Add this block code to service将此块代码添加到服务

services.AddCors(options => options.AddPolicy("CorsPolicy",
        builder =>
        {
            builder.AllowAnyHeader()
                   .AllowAnyMethod()
                   .SetIsOriginAllowed((host) => true)
                   .AllowCredentials();
        }));

and add this block code in configuring app并在配置应用程序中添加此块代码

app.UseCors("CorsPolicy");
app.UseSignalR(routes =>
        {
            routes.MapHub<General>("/hubs/general");
        });

try something like this in your startup configuration class:在你的启动配置类中尝试这样的事情:

app.Map("/CoordinatorHub/negotiate", map =>
{
    map.UseCors(CorsOptions.AllowAll);
    var hubConfiguration = new HubConfiguration 
    {
        // You can enable JSONP by uncommenting line below.
    // EnableDetailedErrors = true,
        // EnableJSONP = true

    };
    map.RunSignalR(hubConfiguration);
});

I had a similar problem that I struggled with for 6 hours.我有一个类似的问题,我挣扎了 6 个小时。

It turned out that I had a slash at the end of my Origins.原来我的起源结尾有一个斜线。

So instead of:所以而不是:

.WithOrigins("https://aaa.azurewebsites.net/")

use:用:

.WithOrigins("https://aaa.azurewebsites.net")

Why the final slash isn't just stripped is beyond my understanding.为什么最后的斜线不只是被剥离超出了我的理解。

Recently i have face the same issue for .Net Core 3.1, Issue start when i deploy in Azure App service and lastly able to solve the issue use the following code.最近我在 .Net Core 3.1 中遇到了同样的问题,当我在 Azure App 服务中部署时问题开始,最后能够使用以下代码解决问题。

I use the following code in ConfigureServices function on Startup.cs file我在 Startup.cs 文件的 ConfigureServices 函数中使用以下代码

services.AddCors(options =>
        {
            var corsUrls = Configuration.GetSection("App:CorsOrigins").Value.ToString()
                      .Split(",", StringSplitOptions.RemoveEmptyEntries)
                             .Select(o => o.Trim('/'))
                             .ToArray();
            options.AddPolicy("CorsPolicy",
            builder =>
            {
                builder.WithOrigins(corsUrls)
                       .AllowAnyHeader()
                       .AllowAnyMethod()
                       .AllowCredentials();
            });
        });

Then add the following code in Configure function然后在Configure函数中添加如下代码

app.UseCors("CorsPolicy");
app.UseEndpoints(endpoints =>
  {
    endpoints.MapControllers();
    endpoints.MapHub<WebhookHub>("/Webhook");
  });

Don't forgot to add the following section in appsetting.json file不要忘记在 appsetting.json 文件中添加以下部分

"App": {
"CorsOrigins": "https://myservice.com" }

Tested on signalR in .Net Core 3.1+ and Angular 8+ versions and android 19+ api level and working on iOS devices too在 .Net Core 3.1+ 和 Angular 8+ 版本和 android 19+ api 级别的 signalR 上进行测试,并且也适用于 iOS 设备

.Net core code .Net核心代码

public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy", builder => builder.WithOrigins("http://localhost:4200")
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials()
                );
            });


            services.AddRazorPages();
            services.AddAccessTokenService();
            services.AddSignalR()
                 .AddHubOptions<ChatHub>(options => options.EnableDetailedErrors = true)
                 .AddJsonProtocol(options =>
                 {
                     options.PayloadSerializerOptions.PropertyNamingPolicy = null;
                  }); ;
            services.AddSingleton<IUserIdProvider, NameUserIdProvider>();

        }



public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();
            app.UseCors("CorsPolicy");

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapRazorPages();
                endpoints.MapHub<ChatHub>("/chathub");
            });

        }

--Angular code replace url and token(optional part) with and it's working-- -- Angular 代码替换了 url 和令牌(可选部分),并且它正在工作--

public startConnection = () => {
  this.hubConnection = new signalR.HubConnectionBuilder()
                          .withUrl(this.url,{ accessTokenFactory: () => this.token},)
                          .build();

  this.hubConnection
    .start()
    .then(() => console.log('Connection started'))
    .catch(err => console.log('Error while starting connection: ' + err))
}

   ngOnInit(): void {
      this.startConnection();

  }

After doing a lot of research I also would like to share what I have faced and how I fixed it.在做了大量研究之后,我还想分享我所面临的问题以及我是如何解决的。

My scenario was;我的情况是; I deployed my .Net Core app on Azure App Services along with Azure SignalR configuration.我在Azure App Services上部署了我的.Net Core应用以及Azure SignalR配置。 Everything was working fine when I run both frontend and backend on my local machine.当我在本地机器上运行前端和后端时,一切正常。 But when I deploy my app on azure services, I could not be able to connect due to this ../Hub/negotiate and cors issue.但是当我在 azure 服务上部署我的应用程序时,由于这个../Hub/negotiate和 cors 问题,我无法连接。

How I fixed;我是如何修复的; First make sure you already enabled cors settings in your api as friends indicated here.首先确保你已经在你的 api 中启用了 cors 设置,正如这里的朋友指出的那样。 I took my example signalR apps from Microsoft docs in this link .我在此链接中从 Microsoft 文档中获取了我的示例 signalR 应用程序。 Finally I realized that in project examples the @aspnet/signalr@1.0.0 package is outdated and moved to @microsoft/signalr .最后我意识到在项目示例中@aspnet/signalr@1.0.0包已过时并移至@microsoft/signalr And In my research I saw in some places that withCredentials should be set to false because by default this value is true and forces the connection to use SSL.在我的研究中,我在某些地方看到withCredentials应该设置为 false,因为默认情况下该值为 true 并强制连接使用 SSL。 My client app is running on local with http and trying to connect https connection.我的客户端应用程序正在使用 http 本地运行并尝试连接 https 连接。 For more of this, refer to this link .有关更多信息,请参阅此链接 In the old signalR npm package this value wasn't set, so as soon as I switched to the new one, withCredentials attribute activated and I set it false.在旧的 signalR npm 包中,这个值没有设置,所以我一切换到新的, withCredentials属性被激活,我把它设置为 false。 All started working fine.一切都开始正常工作。

My final hub builder is like this;我最后的集线器建造者是这样的;

var connection = new signalR.HubConnectionBuilder()
            .withUrl('https://**chat.azurewebsites.net/chat', {
                accessTokenFactory: () => 'InR5cCI6IkpXVCJ9.eyJpZCI6I',
                withCredentials: false
            }).build();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM