SignalR:当预期状态代码“101”时,服务器返回状态代码“200”

问题描述 投票:0回答:1

我想通过 signalR 将我的 maui blazor 应用程序(Windows)连接到 .net blazor 服务器应用程序,以便我可以将消息从服务器推送到客户端。我也用wpf dekstop app测试了,结果是一样的,握手失败。

我正在使用的版本:Microsoft.AspNetCore.SignalR.Client" Version="6.0.1",我尝试了 7.0.1。

有趣的是,@localhost 一切正常。并且 blazor wasm 的 signalR 在同一台服务器上功能齐全。

服务器端托管于@akamai

错误信息详情:

Microsoft.AspNetCore.SignalR.Client.HubConnection: Trace: Waiting on Connection Lock in StartAsyncInner (/_/src/SignalR/clients/csharp/Client.Core/src/HubConnection.cs:247).
Microsoft.AspNetCore.SignalR.Client.HubConnection: Trace: The HubConnection is attempting to transition from the Disconnected state to the Connecting state.
Microsoft.AspNetCore.SignalR.Client.HubConnection: Debug: Starting HubConnection.
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection: Debug: Starting HttpConnection.
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection: Debug: Establishing connection with server at 'https://staging.vetat.work/hub/printertool'.
Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler: Trace: Sending HTTP request POST 'https://staging.asd/hub/printertool/negotiate?negotiateVersion=1'.
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection: Debug: Established connection 'B07mkUpGtdoEwG6C9uQZbA' with the server.
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection: Debug: Starting transport 'WebSockets' with Url: https://staging.vetat.work/hub/printertool.
Microsoft.AspNetCore.Http.Connections.Client.Internal.WebSocketsTransport: Information: Starting transport. Transfer mode: Text. Url: 'wss://staging.vetat.work/hub/printertool?id=UGcgq9uJEOL5hZkA1iZxCQ'.
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection: Error: Failed to start connection. Error starting transport 'WebSockets'.

System.Net.WebSockets.WebSocketException (0x80004005): The server returned status code '200' when status code '101' was expected.
   at System.Net.WebSockets.WebSocketHandle.ValidateResponse(HttpResponseMessage response, String secValue, ClientWebSocketOptions options)
   at System.Net.WebSockets.WebSocketHandle.ConnectAsync(Uri uri, HttpMessageInvoker invoker, CancellationToken cancellationToken, ClientWebSocketOptions options)
   at System.Net.WebSockets.ClientWebSocket.ConnectAsyncCore(Uri uri, HttpMessageInvoker invoker, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.Internal.WebSocketsTransport.DefaultWebSocketFactory(WebSocketConnectionContext context, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.Internal.WebSocketsTransport.StartAsync(Uri url, TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartTransport(Uri connectUrl, HttpTransportType transportType, TransferFormat transferFormat, CancellationToken cancellationToken)
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection: Debug: Skipping transport WebSockets because it failed to initialize.

System.Net.WebSockets.WebSocketException (0x80004005): The server returned status code '200' when status code '101' was expected.
   at System.Net.WebSockets.WebSocketHandle.ValidateResponse(HttpResponseMessage response, String secValue, ClientWebSocketOptions options)
   at System.Net.WebSockets.WebSocketHandle.ConnectAsync(Uri uri, HttpMessageInvoker invoker, CancellationToken cancellationToken, ClientWebSocketOptions options)
   at System.Net.WebSockets.ClientWebSocket.ConnectAsyncCore(Uri uri, HttpMessageInvoker invoker, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.Internal.WebSocketsTransport.DefaultWebSocketFactory(WebSocketConnectionContext context, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.Internal.WebSocketsTransport.StartAsync(Uri url, TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartTransport(Uri connectUrl, HttpTransportType transportType, TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat, CancellationToken cancellationToken)
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection: Debug: Establishing connection with server at 'https://staging.asd/hub/printertool'.
Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler: Trace: Sending HTTP request POST 'https://staging.asd/hub/printertool/negotiate?negotiateVersion=1'.
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection: Debug: Established connection 'trPpDN3vsUzTTUqSu0LdwQ' with the server.
Microsoft.AspNetCore.Http.Connections.Client.HttpConnection: Debug: Starting transport 'ServerSentEvents' with Url: https://staging.asd/hub/printertool.
Microsoft.AspNetCore.Http.Connections.Client.Internal.ServerSentEventsTransport: Information: Starting transport. Transfer mode: Text.
Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler: Trace: Sending HTTP request GET 'https://staging.asd/hub/printertool?id=snz3w-l4JZ8sYDtO8cK9jQ'.

我尝试了 maui 应用程序,我也尝试了调试、日志记录、wpf 应用程序。我希望我可以从服务器向客户端发送消息。

   var url = _configuration[MauiConstants.AppConfig.SignalR];

        _connection = new HubConnectionBuilder()
            .WithUrl(url, options =>
            {
                options.AccessTokenProvider = () => Task.FromResult(token);
            })
            .ConfigureLogging(logging =>
            {
                // Log to the Console
                logging.AddDebug();

                // This will set ALL logging to Debug level
                logging.SetMinimumLevel(LogLevel.Trace);
            })
            .WithAutomaticReconnect()
            .Build();

为了授权,我使用不记名令牌

这是服务器配置:

if (config.SignalR.AllowCors)
    {
        _ = app.UseCors(builder =>
          {
              _ = builder.AllowAnyMethod()
                         .AllowAnyHeader()
                         .AllowCredentials()
                         .WithOrigins(config.SignalR.CorsAddress)
                         .SetIsOriginAllowedToAllowWildcardSubdomains();
          });
    }


_ = authenticationBuilder.AddJwtBearer(AuthConstant.Scheme.PrinterTool, options =>
    {
        options.RequireHttpsMetadata = false;
        options.SaveToken = true;
        options.Audience = $"{Audience.PrinterTool:G}";
        var signingKey = Convert.FromBase64String(secretKey);
        options.TokenValidationParameters = new TokenValidationParameters
        {
            AuthenticationType = AuthConstant.Scheme.PrinterTool,
            ValidateIssuer = false,
            ValidateAudience = true,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(signingKey),
            ClockSkew = TimeSpan.FromMinutes(Convert.ToDouble(config.AdminAppAuthentication.ExpiresIn))
        };

        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {
                if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                {
                    context.Response.Headers["Token-Expired"] = "true";
                }

                return Task.CompletedTask;
            },
            OnMessageReceived = context =>
            {
                //If the request is for our hub
                var path = context.HttpContext.Request.Path;

                if (path.StartsWithSegments(config.SignalR.PrinterToolMainHubRoute))
                {
                    var authorization = context.Request.Headers?.Authorization.FirstOrDefault(a => a.StartsWith("Bearer "));
                    if (!string.IsNullOrEmpty(authorization))
                    {
                        context.Token = authorization.Substring("Bearer ".Length);
                    }
                }

                return Task.CompletedTask;
            }
        };
    });
c# .net .net-core websocket signalr
1个回答
0
投票

我想这个问题已经解决了。 我遇到了同样的问题,我解决了更改产品服务器上的 nginx 配置

更改此:

proxy_set_header Connection keep-alive;

通过这个:

proxy_set_header Connection $http_connection;

完成nginx配置:

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name api.your-domain.com;
    add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;

    ssl_certificate /etc/nginx/ssl/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/live/your-domain.com/privkey.pem;

    location / {
        proxy_pass http://172.17.0.1:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $http_connection;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_headers_hash_max_size 512;
        proxy_headers_hash_bucket_size 128;
    }
}

来源:Nginx 背后的 ASP.NET Core 中的 SignalR

© www.soinside.com 2019 - 2024. All rights reserved.