使用IdentityServer4时,无法访问我的SignalR端点(从javascript)。

设置身份服务器4安装+信号器。不幸的是,我不完全理解日志输出。

CORS request made for path: /hubs/SampleMessageHub from origin: >
http://localhost:4200 but was ignored because path was not for an allowed
IdentityServer CORS endpoint


启动文件

 public class Startup
    {
        public IConfiguration Configuration { get; }
        public IWebHostEnvironment _environment { get; }

        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            Configuration = configuration;
            _environment = env;
        }

        public void ConfigureServices(IServiceCollection services)
        {

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

            services.AddSignalR();

            services.AddControllersWithViews();

            services.AddIdentityServer(options =>
            {
                options.Events.RaiseSuccessEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseErrorEvents = true;
            })
                    .AddInMemoryIdentityResources(Config.GetIdentityResources())
                    .AddInMemoryApiResources(Config.GetApiResources())
                    .AddInMemoryClients(Config.GetClients())
                    .AddDeveloperSigningCredential()
                    .AddCustomUserStore();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseCors("MyPolicy");

            app.UseWebSockets();
            app.UseStaticFiles();
            app.UseIdentityServer();

            app.UseRouting();

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

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<SampleHub>("/hubs/SampleMessageHub");

                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }


配置看起来像这样:

 public class Config
    {
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
                {
                    new IdentityResources.OpenId(),
                    new IdentityResources.Profile(),
                    new IdentityResources.Email()
                };
        }
        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {

                new ApiResource("hubs/SampleMessageHub", "SignalR Hub Resources")
                {
                    // this is needed for introspection when using reference tokens
                    ApiSecrets = { new Secret("secret".Sha256()) }
                }
            };
        }

        // clients want to access resources (aka scopes)
        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                new Client
                {
                    ClientId = "angular-test",
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AccessTokenType = AccessTokenType.Jwt,
                    AccessTokenLifetime = 3600,
                    IdentityTokenLifetime = 3600,
                    UpdateAccessTokenClaimsOnRefresh = true,
                    SlidingRefreshTokenLifetime = 15,
                    AllowOfflineAccess = true,
                    RefreshTokenExpiration = TokenExpiration.Absolute,
                    RefreshTokenUsage = TokenUsage.OneTimeOnly,
                    AlwaysSendClientClaims = true,
                    Enabled = true,
                    AlwaysIncludeUserClaimsInIdToken = true,
                    RedirectUris = new List<string>() { "http://localhost:4200/", "http://localhost:4200/silent-refresh.html" },
                    AllowedScopes = {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.Email
                    },
                    PostLogoutRedirectUris = new List<string>() { "http://localhost:4200/" },
                    AllowAccessTokensViaBrowser = true,
                    RequireConsent = false
                }
            };
        }
    }


和一个真正简单的Hub:

public class SampleHub : Hub<ISampleHub>
    {
        public SampleHub()
        {

        }

        Task SendMessage(string message)
        {
            Console.WriteLine("Message received: " + message);
            return Task.CompletedTask;
        }
    }


身份服务器的日志输出如下所示:


    dbug: IdentityServer4.Hosting.CorsPolicyProvider[0]
      CORS request made for path: /hubs/SampleMessageHub from origin:
     http://localhost:4200 but was ignored because path was not for an
     allowed IdentityServer CORS endpoint
    info: Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware[10]
      No CORS policy found for the specified request.
    info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint '/hubs/SampleMessageHub'
    info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/hubs/SampleMessageHub'
    info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 309.1009ms 101


我在角度上的错误是:

 [2019-10-02T09:35:27.872Z] Information: WebSocket connected to wss://localhost:5001/hubs/SampleMessageHub.
core.js:4002 ERROR Error: Error parsing handshake response: TypeError: Right-hand side of 'instanceof' is not callable
    at HubConnection.push../node_modules/@aspnet/signalr/dist/esm/HubConnection.js.HubConnection.processHandshakeResponse (HubConnection.js:372)
    at HubConnection.push../node_modules/@aspnet/signalr/dist/esm/HubConnection.js.HubConnection.processIncomingData (HubConnection.js:322)
    at WebSocketTransport.HubConnection.connection.onreceive (HubConnection.js:65)
    at WebSocket.webSocket.onmessage (WebSocketTransport.js:107)
    at WebSocket.wrapFn (zone.js:1279)
    at ZoneDelegate.invokeTask (zone.js:431)
    at Object.onInvokeTask (core.js:26246)
    at ZoneDelegate.invokeTask (zone.js:430)
    at Zone.runTask (zone.js:198)
    at ZoneTask.invokeTask [as invoke] (zone.js:513)


如果我在没有身份服务器的情况下进行新项目,那么一切都会按预期进行。某种程度上需要对SignalR端点进行一些配置-但是这种配置看起来如何?

在此先感谢您的帮助。

最佳答案

也尝试在AllowedCorsOrigins方法中添加GetClients()属性。
例如

        public IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                new Client
                {
                    AllowedCorsOrigins =
                    {
                        "http://localhost:4200/",

                    },
                   // Rest of the properties
                }
            }
        }



原因是您现在允许CORS域(localhost:4200)访问您的API。

07-26 04:33