【问题标题】:CORS policy don't want to work with SignalR and ASP.NET coreCORS 策略不想与 SignalR 和 ASP.NET 核心一起使用
【发布时间】:2019-07-16 08:17:03
【问题描述】:

我的 ASP.NET 核心 API 和 Angular 客户端有问题。我想实现 SignalR 以在 API 和 Angular 之间建立连接。 cors 策略已经在我们的客户端和 API 上激活,因为我们已经可以使用我们的客户端从 API 检索数据。但现在的问题是,当我尝试使用 SignalR 时,我收到了 CORS POLICY 错误:

访问 XMLHttpRequest 在 'http://localhost:50501/CoordinatorHub/negotiate' 来自原点 'http://localhost:4200' 已被 CORS 策略阻止:响应 预检请求未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。

但我们 API 的 Startup.cs 中已经有 cors 政策,就像这样:

在 ConfigureServices 方法中:

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

在 Configure 方法内部:

app.UseCors("AllowSpecificOrigin");

在我们的客户端中,我们只想尝试在 API 和客户端之间建立连接,就像这样:

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

【问题讨论】:

标签: angular asp.net-core cors signalr angular7


【解决方案1】:

在做了很多研究之后,我还想分享一下我所面临的问题以及我是如何解决的。

我的情况是;我在Azure App Services 上部署了我的.Net Core 应用程序以及Azure SignalR 配置。当我在本地机器上同时运行前端和后端时,一切正常。但是当我在 azure 服务上部署我的应用程序时,由于 ../Hub/negotiate 和 cors 问题,我无法连接。

我是如何解决的;首先确保您已经在您的 api 中启用了 cors 设置,正如朋友在此处指出的那样。我在link 中从 Microsoft 文档中获取了我的示例 signalR 应用程序。最后我意识到,在项目示例中,@aspnet/signalr@1.0.0 包已过时并移至@microsoft/signalr。在我的研究中,我在某些地方看到 withCredentials 应该设置为 false,因为默认情况下此值为 true 并强制连接使用 SSL。我的客户端应用程序使用 http 在本地运行并尝试连接 https 连接。有关更多信息,请参阅此link。在旧的 signalR npm 包中,没有设置这个值,所以当我切换到新的包时,withCredentials 属性被激活,我将其设置为 false。一切开始正常。

我的最终集线器构建器是这样的;

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

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,我为此苦苦挣扎了 6 个小时。

    原来我的起源结尾有一个斜线。

    所以而不是:

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

    使用:

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

    我不理解为什么最后的斜线不被删除。

    【讨论】:

      【解决方案3】:

      接受的答案对我不起作用,所以我决定在这里写下对我有用的答案。以防有人偶然发现同样的问题。

      在 Angular 9 上玩 signalR 时,我在本地测试中遇到了同样的问题。

      我通过将我的 Asp NET Core (3.1) 应用程序 URL 从 https 切换到 http 解决了这个问题。如果您使用的是 Visual Studio,

      1. 只需右键单击项目属性 -> 调试。
      2. 取消选中启用 SSL

      另外不要忘记在 Angular App 中更改 URL 上的端口。所以基本上角度应用程序中的 URL 将是这样的

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

      而配置方法中的相关代码是这样的

      app.UseHttpsRedirection();
      app.UseStaticFiles();
      
         
      app.UseRouting();
      app.UseCors("_myAllowSpecificOrigins");
      
      app.UseAuthorization();
      
      app.UseEndpoints(endpoints =>
      {
          endpoints.MapRazorPages();
          endpoints.MapHub<ChatHub>("/hub");
      });
      

      在您的 configureServices 方法中,我关注了

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

      希望这会有所帮助!

      更新

      如果您只是在本地计算机上使用示例,您还可以尝试在安全模式下运行 chrome,如 here 所述

      在我的 Mac 上,我只是简单地从终端运行命令

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

      有了这个,您应该能够在没有 CORS 的情况下运行您的示例

      【讨论】:

      • 你先生为我节省了 3 个小时的时间,我一直在寻找一种不需要在角度侧设置代理的解决方案。谢谢!
      • 深入挖掘后发现的另一个选项是 builder .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials() .SetIsOriginAllowed(origin =&gt; new Uri(origin).Host == "localhost");
      • 我尝试了你的步骤@kuldeep,但我收到错误为“localhost:64574/api/location/negotiate”ERR_CONNECTION_REFUSED。 PS:我正在使用 ionic,并试图从 android 模拟器中访问 api。
      • 我不知道 ionic,它是基于浏览器的吗?我建议如果是,那么您可以像我建议的那样在安全模式下打开 chrome,或者您可以设置您的 API 以在 cors 策略中允许 localhost,就像上面的评论一样!
      【解决方案4】:

      在 .Net Core 3.1+ 和 Angular 8+ 版本和 android 19+ api 级别的 signalR 上进行测试,也可以在 iOS 设备上运行

      .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 代码替换 url 和 token(可选部分) 并且它正在工作--

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

      【讨论】:

        【解决方案5】:

        最近我在 .Net Core 3.1 中遇到了同样的问题,当我在 Azure App 服务中部署时问题开始,最后能够使用以下代码解决问题。

        我在 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();
                    });
                });
        

        然后在Configure函数中添加如下代码

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

        不要忘记在 appsetting.json 文件中添加以下部分

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

        【讨论】:

          【解决方案6】:

          我根据这个link解决了我的问题

          将此块代码添加到服务中

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

          并在配置应用程序中添加此块代码

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

          【讨论】:

            【解决方案7】:

            注意这可以应用于 .net core 3.1

            正如微软文档中所述,它似乎不起作用 docs

            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                // Preceding code ommitted.
                app.UseRouting();
            
                app.UseCors();
            
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            
                // Following code ommited.
            }
            

            警告

            使用端点路由,CORS 中间件必须配置为 在对 UseRouting 和 UseEndpoints 的调用之间执行。不正确 配置将导致中间件停止正常运行。

            但是,如果您首先移动 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.
            }
            

            【讨论】:

              【解决方案8】:

              在你的启动配置类中尝试这样的事情:

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

              【讨论】:

                猜你喜欢
                • 2020-09-21
                • 2019-11-16
                • 1970-01-01
                • 2018-07-17
                • 2019-11-30
                • 2020-08-13
                • 2020-06-10
                • 2021-07-20
                • 2016-12-14
                相关资源
                最近更新 更多