Angular 和 .NET Core 的 SignalR CORS 问题

Posted

技术标签:

【中文标题】Angular 和 .NET Core 的 SignalR CORS 问题【英文标题】:SignalR CORS issue with Angular and .NET Core 【发布时间】:2021-12-06 05:10:58 【问题描述】:

我知道有很多关于这个主题的问题和答案,但没有一个符合我的具体问题。

我正在使用以下版本

角 10.0.14 @aspnet/signalr 1.0.27 ASP.NET Core 3.1

版本更新:

我刚刚将 @aspnet/signalr 1.0.27 替换为 @microsoft/signalr 5.0.11 -> 同样的问题。

在我在 Angular 前端添加 accessTokenFactory 之前,SignalR 连接工作正常。

前端

this.hubConnection = new signalR.HubConnectionBuilder()
  .withUrl(`$environment.bzApiBaseUrl/hubs/heartbeat`, 
    accessTokenFactory: () => token
  )
  .build();

this.hubConnection
  .start()
  .then(() => 
    console.log('SignalR: Heartbeat - connection started');

    this.hubConnection.on('beat', () => 
      console.log('SignalR: Heartbeat - Heartbeat received');
    );
  )
  .catch(err => console.log('SignalR: Heartbeat - error while starting connection: ' + err));
  );

当我从HubConnectionBuilder 中删除accessTokenFactory 时,连接建立。

后端

services.AddCors(options =>

    options.AddPolicy(
        name: MyAllowSpecificOrigins,
        builder =>
        
            builder
                .WithOrigins(CorsSettings.TargetDomain)
                .AllowAnyHeader()
                .AllowAnyMethod()
                .SetIsOriginAllowed((host) => true)
                .AllowCredentials();
        );
);

CorsSetting 域的值是http://localhost:4200,前端正在运行。

app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(e =>

    e.MapControllers();
    e.MapHub<HeartbeatHub>("/api/hubs/heartbeat");
);

添加accessTokenFactory后,浏览器控制台会出现以下错误:

WebSocketTransport.js:70 
WebSocket connection to 'ws://localhost:33258/api/hubs/heartbeat?id=BpBytwkEatklNR-XqGtabA&access_token=eyJ0eXAiOiJKV1QiLCJhbGci... failed:

Utils.js:190 
Error: Failed to start the transport 'WebSockets': undefined

dashboard:1 
Access to resource at 'http://localhost:33258/api/hubs/heartbeat?id=iWuMeeOKkWCUa8X9z7jXyA&access_token=eyJ0eXAiOiJKV1QiLCJhbGci...' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我不理解 CORS 问题,因为它似乎是通过使用 accessTokenFactory 向查询字符串添加令牌来引发的。

我试过了:

将后端 URL 添加到 CORS 源(根据文档不需要) app.UseSignalR 代替 app.UseEndpoints 禁用 app.UseHttpsRedirection() 以不同方式更改了注册中间件的顺序 .SetIsOriginAllowed((host) => true) 在 .AllowCredentials() 之后

更新

HttpTransportType 设置为LongPolling 时建立连接。它不适用于WebSocketsServerSentEvents

app.UseEndpoints(e =>

    e.MapControllers();
    e.MapHub<HeartbeatHub>("/api/hubs/heartbeat", options =>
    
        options.Transports = HttpTransportType.LongPolling;
    );
);

在使用长轮询时,令牌似乎作为 HTTP 标头而不是查询字符串参数发送。令牌很长,所以我突破了最大值。使用 WebSockets 或 ServerSentEvents 时允许的 URL 长度。但我仍然不知道为什么这会导致 CORS 异常。

【问题讨论】:

请尝试@microsoft/signalr,因为@aspnet\signlar 已被弃用。 @F*** 我换了包没有任何效果,还是一样的错误。 顺序很重要:***.com/questions/59468525/… @Kiril1512 谢谢提示,但是改了顺序还是一样的错误。 @SebastianS。是的,但是你的“使用”呢?您应该尝试将“UseAuthentication”和“UseAuthorization”放在“UseCors”和其他类似“UseRouting”之前。 【参考方案1】:

浏览器不支持 websocket 的标头,因此必须将不记名令牌添加为查询字符串参数。由于不记名令牌的长度,我们达到了 URL 的最大长度。我们可以缩短我们的令牌或使用参考令牌,另请参阅:https://github.com/aspnet/SignalR/issues/1266

希望这对其他人也有帮助。

【讨论】:

以上是关于Angular 和 .NET Core 的 SignalR CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章

ASP.Net Core、Angular2 和基于令牌的身份验证

IIS 上的 Net Core Cors 和 Angular 应用程序

Angular 和 Asp.Net Core - 启用 2 因素身份验证

Angular 和 .NET Core 的 SignalR CORS 问题

net.core 和 angular4 应用程序的 Cors 问题 - 适用于 azurewebsites.net 域而不是自定义

使用 MSAL 保护 ASP.Net Core Web API 和 Angular App