当 React App 尝试通过 SignalR 连接到启用 Windows 身份验证的 .NET CORE Web App 时出现 CORS 错误

Posted

技术标签:

【中文标题】当 React App 尝试通过 SignalR 连接到启用 Windows 身份验证的 .NET CORE Web App 时出现 CORS 错误【英文标题】:CORS Error when React App tries to connect via SignalR to .NET CORE Web App having Windows Authentication enabled 【发布时间】:2021-08-15 00:14:59 【问题描述】:

我正在尝试使用 SignalR 将数据从 React App 发送到 .NET Core Web App。 .NET Core Web 应用启用了 Windows 身份验证。启用 Windows 身份验证后,当我的 React 应用程序尝试通过 SignalR 向 .NET Core 应用程序发送消息时,我收到了 CORS 错误。 如果我禁用 Windows 身份验证并启用匿名身份验证,它工作正常。

您能否帮助我提供宝贵的意见以使连接正常工作?

React JS 应用代码如下所示:

const hubConnection = new HubConnectionBuilder()
      .withUrl(window.config.APP_URL, options)
      .withAutomaticReconnect()
      .build();

    this.setState( hubConnection , () => 
      this.state.hubConnection
        .start()
        .then(() => console.log("SignalR Connection started!"))
        .catch((err) =>
          console.log("SignalR Error while establishing connection :(", err)
        );
    );
  

  sendMessage = () => 
    console.log("sendMessage() Properties: ", this.props);

    const signalRMessage = 
      UserName: this.props.userName,
    ;
    this.state.hubConnection
      .invoke("SendMessage", signalRMessage)
      .catch((err) => console.error(err));
  ;

我尝试显式添加“Access-Control-Allow-Origin”标头,如下所示。但我仍然看到 CORS 错误。

componentDidMount() 

    let options = 
      httpClient: 
        post: (url, httpOptions) => 
    
          // httpOptions.headers = 
          //   ...httpOptions.headers,
          //   "Access-Control-Allow-Origin": window.config.CORS_ALLOW_ORIGIN_URL,
          //   //"Access-Control-Allow-Methods": "POST, GET, HEAD",
          // ;
          // httpOptions.method = "POST";
          // httpOptions.url = url;
    
          // return httpOptions;

          const headers = 
            ...httpOptions.headers,
            "Access-Control-Allow-Origin": window.config.CORS_ALLOW_ORIGIN_URL,
            "Access-Control-Allow-Methods": "POST, GET, HEAD",
          ;
          let newResponse = ;
    
          return axios.post(url, ,  headers ).then(response => 
            return (newResponse = 
              statusCode: response.status,
              statusText: response.statusText,
              content: JSON.stringify(response.data)
            );
          );
    
          
       
    ;

以下是我在 React App 端的控制台日志中看到的 CORS 错误: enter image description here

public void ConfigureServices(IServiceCollection services)
        
            services.AddAuthentication(IISDefaults.AuthenticationScheme);

            services.AddRazorPages();

            services.AddCors(options =>
            
                options.AddPolicy("ClientPermissionPolicy", policy =>
                
                    
                    policy.WithOrigins("https://xxxx.com")
                        .AllowAnyHeader()
                        .AllowAnyMethod().AllowCredentials();
                );
            );            

            ...
        

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        

            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
            
            else
            
                app.UseExceptionHandler("/Error");
                
                app.UseHsts();
            

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

            app.UseCors("ClientPermissionPolicy");       

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            
                endpoints.MapRazorPages();
                endpoints.MapHub<TapHub>("/hubs/tap");
            );

                     
        

在***中浏览了许多帖子并在下面尝试但徒劳无功。

在配置()中:

app.UseCors(builder => builder.WithOrigins("https://xxxx.com").AllowAnyMethod().AllowAnyHeader().AllowCredentials());

在 ConfigureServices() 中:

services.AddCors(选项 => options.AddPolicy("ClientPermissionPolicy", policy => policy.WithOrigins("https://xxxxx.com") .AllowAnyHeader() .AllowAnyMethod().AllowCredentials() .SetIsOriginAllowed((host) => true); ); );

试过 AllowAnyOrigin()

尝试删除 AllowCredentials()

就像我上面说的,如果我禁用 Windows 身份验证并启用匿名身份验证,它就可以正常工作。在匿名身份验证的情况下,React App 成功连接到中心端点。仅当我启用 Windows 身份验证时,CORS 错误才会出现。我需要为我的要求启用 Windows 身份验证。请求您帮助解决问题。

谢谢!

【问题讨论】:

【参考方案1】:

有点晚了,但是我现在遇到了类似的问题。即使启用了 CORS,它仍然拒绝了我。最后,我发现问题出在

app.UseEndpoints(endpoints =>

    endpoints.MapControllers();
);

当我将 CORS 包含在这部分中时,它开始起作用了……终于

app.UseEndpoints(endpoints =>

    endpoints.MapControllers().RequireCors("ClientPermissionPolicy");
);

【讨论】:

【参考方案2】:

你必须在 UseRouting 和 UseAutorization 之间放置 UseCors

app.UseRouting();
app.UseCors("ClientPermissionPolicy");      
app.UseAuthorization();

也许您可以尝试将 AddCors 移到 ConfigureServices 方法的顶部

只是测试结果我会用这个

public void ConfigureServices(IServiceCollection services)

    services.AddCors(o => o.AddPolicy("ClientPermissionPolicy", builder =>
            
                builder.AllowAnyOrigin()
                       .AllowAnyMethod()
                       .AllowAnyHeader();
            ));
.....

只有在可行的情况下,我才会尝试使用特定的来源。

【讨论】:

谢谢@Serge/ 尝试了同样的方法,但我仍然收到 CORS 错误。 从源“xxxxxx.com”访问“localhost:44332/hubs/tap/negotiate?negotiateVersion=1”处的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:没有“Access-Control-Allow-Origin”标头出现在请求的资源上。我将 UseCors 放在 UseRouting 和 UseAutorization 之间,并将 AddCors 移到 ConfigureServices 方法的顶部。 @SiddN 我更新了答案,你可以再试一次。 谢谢。试过这个。仍然收到相同的 CORS 错误。 :(【参考方案3】:

对于使用 .NET Core 3.1 的用户,这里有一个完整的解决方案(前端到后端):

我的问题:当我在我的 Web API 上启用 Windows 身份验证时,我无法从我的 react 应用程序获取调用到我的 .NET Core 3.1 Web API,CORS 吓坏了。使用匿名身份验证它可以工作,但在启用 Windows 身份验证时不能。

1.launchSettings.json

这将仅用于您的开发环境,请确保您的产品服务器上的 IIS 中也启用了 Windows 身份验证。


  "iisSettings": 
    "windowsAuthentication": true,
    "anonymousAuthentication": false,
    "iisExpress": 
      "applicationUrl": "http://localhost:58747",
      "sslPort": 0
    
  ,
 ... more settings if any

2.Startup.cs:

CORS 政策在此处启用。方法的顺序在这里很重要。此外,您不需要在 web.config 中设置这些

public void ConfigureServices(IServiceCollection services)

    services.AddCors(options =>
    
        options.AddPolicy("CorsPolicy", //give it the name you want
                       builder =>
                       
                            builder.WithOrigins( "http://localhost:3000", //dev site
                                                "production web site"
                                               .AllowAnyHeader()
                                               .AllowAnyMethod()
                                               .AllowCredentials();
                       );
    );

    //database services here

    services.AddControllers();


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

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

    app.UseRouting();

    // global policy same name as in the ConfigureServices()
    app.UseCors("CorsPolicy");

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

3.控制器:

using Microsoft.AspNetCore.Cors;
... your other usings

namespace ProjectTest.Controllers

    [ApiController]
    [EnableCors("CorsPolicy")] //THIS HERE needs to be the same name as set in your startup.cs
    [Route("[controller]")]
    public class FooController:Controller
    
        [HttpGet("getTest")]
        public JsonResult GetTest()
        
            return Json("bar");
        
    

4.React Component fetch 调用示例:

“凭据:'include'”是秘密

await fetch('http://localhost:3000/Foo/getTest', 
    method: 'GET',
    credentials: 'include'
).then(resp => resp.json());

【讨论】:

【参考方案4】:

如here所述,出现问题的原因是:

IIS 的 Windows 身份验证发生在 ASP.NET Core 运行之前,即 ASP.NET Core CORS 实现无法处理 OPTIONS 请求(因为 浏览器不会随它一起发送您的 Windows 凭据)。唯一的 真正的解决方案是使用 IIS CORS 模块,因为它之前运行 Windows 身份验证并可以处理未经身份验证的 CORS 请求。

【讨论】:

以上是关于当 React App 尝试通过 SignalR 连接到启用 Windows 身份验证的 .NET CORE Web App 时出现 CORS 错误的主要内容,如果未能解决你的问题,请参考以下文章

尝试通过uniapp仿微信页面

在 azure 上部署后 SignalR 无法正常工作。在 localhost 上工作

SignalR在React/Go技术栈的实践

vue中SignalR全局封装

Signalr 实现心跳包

React.js 搭建温度控制 App 项目