Не удалось подключиться к SignalR в веб-сборке Blazor - PullRequest
1 голос
/ 18 марта 2020

Я пытаюсь подключиться к сервису SignalR из моего клиента веб-сборки Blazor, но мне кажется, что это не удается на CORS. Это код в моем файле бритвы.

m_connection = new HubConnectionBuilder()
    .WithUrl(myMircoServiceUrl, options =>
    {
       options.AccessTokenProvider = () => Task.FromResult(userService.Token);
    })
   .WithAutomaticReconnect()
   .Build();
await m_connection.StartAsync();

Затем в журнале веб-сборки я вижу следующую ошибку:

Доступ к выборке в 'xxxx /gotiate ?gotiateVersion = 1 'from origin' http://localhost: 5010 'заблокировано политикой CORS: Ответ на предпечатный запрос не проходит проверку контроля доступа: заголовок «Access-Control-Allow-Origin» отсутствует на запрашиваемый ресурс. Если непрозрачный ответ удовлетворяет вашим потребностям, установите режим запроса «no-cors», чтобы получить ресурс с отключенным CORS.

Я добавил следующую политику CORS в конфигурацию своего сервера Blazor и нечто подобное в Конфигурация микросервиса:

        app.UseResponseCompression();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseBlazorDebugging();
        }
        else
        {
            app.UseExceptionHandler(@"/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseCookiePolicy();
        app.UseAuthentication();
        app.UseAuthorization();

        app.UseCors(policy => policy
            .WithOrigins("http://localhost:5010")
            .AllowAnyHeader()
            .AllowAnyMethod());

        app.UseClientSideBlazorFiles<Client.Program>();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapFallbackToClientSideBlazor<Client.Program>(@"index.html");
        });

Кто-нибудь понял, что может быть не так?

Обновление 1

Теперь я вижу следующую ошибку в Chrome console:

do tnet. js: 1 Соединение WebSocket с 'ws: // localhost: 5000 / hubs / posts? Id = 9Jxs0DhP924zgw_eIeE9Lg' не удалось: ошибка аутентификации HTTP; допустимые учетные данные недоступны

Обновление 2

Я удалил атрибут [Authorize] из концентратора SignalR, и теперь он подключается. И я могу отправлять сообщения в хаб. Проблема в том, что есть причина для этого атрибута, потому что я не хочу, чтобы люди могли подписываться на сообщения, которые не для них

Обновление 3

Все еще нет прогресса , Рассматривая извлечение аутентификации на отдельный микросервис с использованием IdentityServer4. Последнее состояние: у меня есть следующие подпрограммы запуска:

  • Микросервис: gist.github.com/njannink/15595b77ffe1c0593be1a555fa37f83f
  • Blazor-сервер: gist.github.com/njannink/7302a888110eb669104454994994994994995994994994991991991994994994994994994104994994994999 *
  • Клиент Blazor: gist.github.com/njannink/add2568cbf48c8b3c070ccd4f28fd127

Ответы [ 2 ]

1 голос
/ 24 марта 2020

В моем случае, ASP. NET Core 2.2 У меня есть API, из которого я хочу использовать SignalR из API для подключения к моему клиентскому приложению.

У меня есть проекты для

  1. Веб-API
  2. IdentityServer4
  3. MVC Клиент

С ASP. NET Базовая идентификация как для управление пользователями

Для того, чтобы ваш пользователь прошел аутентификацию, вам необходимо реализовать IUserIdProvider, подобный этому

 public class IdBasedUserIdProvider : IUserIdProvider
 {
      public string GetUserId(HubConnectionContext connection)
      {
           //TODO: Implement USERID Mapper Here
           //throw new NotImplementedException();
           //return whatever you want to map/identify the user by here. Either ID/Email
           return connection.User.FindFirst("sub").Value;
      }
 }

. С этим я удостоверяюсь, что продвигаюсь по ID / электронной почте к методу I звоню либо с сервера, либо с клиента. Хотя я всегда могу использовать .User на HubContext, и он отлично работает.

В моем файле Startup.cs для Web API я нашел

public void ConfigureServices(IServiceCollection services)
{
     services.AddCors(cfg =>
           {
                cfg.AddDefaultPolicy(policy =>
                {
                     policy.WithOrigins(Configuration.GetSection("AuthServer:DomainBaseUrl").Get<string[]>())
                     .AllowAnyHeader()
                     .AllowAnyMethod()
                     .AllowCredentials()
                     .SetIsOriginAllowed((_) => true)
                     .SetIsOriginAllowedToAllowWildcardSubdomains();
                });
           });
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, UserManager<AppUser> userManager,
           RoleManager<IdentityRole> roleManager){

    app.UseCors();

}

NOTE Configuration. *

Надеюсь, это поможет вашей ситуации.

0 голосов
/ 24 марта 2020

Лучшее решение действительно, как Ismail Umer , описанное с использованием отдельной службы аутентификации с использованием чего-то вроде IdentityServer4. И использовать этот сервис во всех других сервисах. Это то, что я сделаю в следующей итерации.

В качестве краткосрочного решения я временно переместил серверную часть Blazor в свою службу API и использовал метод двойной аутентификации (JWT header или cook ie).

        var key = Encoding.UTF8.GetBytes(m_configuration[@"SecurityKey"]);
        services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = @"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ValidateLifetime = true
                };
            })
            .AddCookie();

        // TODO: For time being support dual authorization. At later stage split in various micro-services and use IdentityServer4 for Auth
        services.AddAuthorization(options =>
        {
            var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
                CookieAuthenticationDefaults.AuthenticationScheme,
                JwtBearerDefaults.AuthenticationScheme);
            defaultAuthorizationPolicyBuilder =
                defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
            options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
        });
...