Blazor WebAssembly 401 Неавторизован, даже если я авторизован - PullRequest
0 голосов
/ 10 июля 2020

Я использую Blazor WebAssembly Asp.Net Core hosted PWA и интегрировал в него AspNetCore.Identity. Я создал AuthenticationStateProvider на стороне клиента, и теперь я хочу разрешить пользователю доступ к контроллеру, где он должен быть авторизован.

Я тестировал через почтальона, пользователи были созданы и сохранены в БД как aspnetusers с правильными учетными данными. Контроллер входа / учетной записи работает так, как я хотел.

Когда пользователь авторизован, он сообщает об этом исключении в браузере при доступе к запросу авторизованного контроллера:

Microsoft.AspNetCore.Components .WebAssembly.Rendering.WebAssemblyRenderer [100] Компонент рендеринга необработанного исключения: Код состояния ответа не указывает на успех: 401 (Неавторизовано). System. Net .Http.HttpRequestException: код состояния ответа не указывает на успех: 401 (неавторизованный).

Startup.cs (ConfigureServices -Method):

...
    serviceCollection.AddDbContext<SQLiteTestDbContext>(options =>
                {
                    options.UseSqlite(config["ConnectionStrings:SQLiteTestConnection"]);
                });
                serviceCollection.AddDefaultIdentity<IdentityUser>()
                    .AddEntityFrameworkStores<SQLiteTestDbContext>()
                    .AddDefaultTokenProviders();

    services.AddAuthentication(x =>
                    {
                        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    })
                    .AddJwtBearer(options =>
                    {
                        options.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuer = true,
                            ValidateAudience = true,
                            ValidateLifetime = true,
                            ValidateIssuerSigningKey = true,
                            ValidIssuer = Configuration["JwtIssuer"],
                            ValidAudience = Configuration["JwtAudience"],
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"]))
                        };
                    });

    services.AddHttpContextAccessor();
                services.Configure<IdentityOptions>(options =>
                    options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier);
...

 

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      
    ...
        app.UseAuthentication();
        app.UseAuthorization();
    ...
    }

Program.cs на стороне клиента


    public static async Task Main(string[] args)
            {
                var builder = WebAssemblyHostBuilder.CreateDefault(args);
                builder.RootComponents.Add<App>("app");
                builder.Logging.SetMinimumLevel(LogLevel.Warning);
    
                //Registering Shared-Library models
                builder.Services.AddScoped<ObjectModel>();

                builder.Services.AddBlazoredLocalStorage();
                builder.Services.AddAuthorizationCore();
                builder.Services.AddScoped<AuthenticationStateProvider, ApiAuthenticationStateProvider>();
                builder.Services.AddScoped<IAuthService, AuthService>();
    
                //Registered BlazorContextMenu Service
                builder.Services.AddBlazorContextMenu();
    
                //Registering FileReader service, for image upload -> Azure
                builder.Services.AddFileReaderService(options => options.UseWasmSharedBuffer = true);
                builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
    
                await builder.Build().RunAsync();
            }

Мой контроллер с атрибутом авторизации:


    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
        [Route("api/[controller]")]
        [ApiController]
        public class ObjectController : ControllerBase
        {
....
    

1 Ответ

1 голос
/ 11 июля 2020

Примечание:

  1. Когда ваш пользователь пытается получить доступ к защищенной (помеченной атрибутом Authorize) странице на клиенте, он должен сначала войти в систему или зарегистрироваться.

  2. Для регистрации он должен быть перенаправлен к контроллеру учетных записей, где вы должны создать нового пользователя и добавить его в базу данных (вы сказали, что «интегрировали в него AspNetCore.Identity»), и это нормально. ... и должны использоваться для аутентификации и проверки личности пользователя. Контроллер вашей учетной записи также должен создать токен Jwt, который следует передать клиентскому приложению и сохранить в локальном хранилище.

  3. Теперь, когда ваш пользователь пытается получить доступ к защищенным ресурсам в вашем Интернете Конечные точки API, вы должны получить токен Jwt из локального хранилища и добавить его в заголовок запроса. Если вы это сделаете, несанкционированный ответ останется в прошлом.

  4. Custom AuthenticationStateProvider может быть хорошим местом, из которого вы можете управлять хранением токена Jwt в локальном хранилище и его извлечением для исходящих вызовов HTTP-запросов.

Вот пример кода, поясняющий, что вам следует делать:

@code {
    WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        var token = await TokenProvider.GetTokenAsync();
        forecasts = await Http.GetJsonAsync<WeatherForecast[]>(
            "api/WeatherForecast",
            new AuthenticationHeaderValue("Bearer", token));
    }
}

Примечание. TokenProvider - это настраиваемый AuthenticationStateProvider, который определяет метод, называемый GetTokenAsyn c, который предоставляет (считывает токен Jwt из локального хранилища и передает его в вызывающий код) токен Jwt

Надеюсь, это поможет ...

...