【问题标题】:Blazor WebAssembly 401 Unauthorized even when I am authorizedBlazor WebAssembly 401 未经授权,即使我已获得授权
【发布时间】:2023-03-20 19:19:02
【问题描述】:

我正在使用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
        {
....
    

【问题讨论】:

标签: c# asp.net-core asp.net-identity blazor blazor-webassembly


【解决方案1】:

注意:

  1. 当您的用户尝试访问客户端上受保护的(使用 Authorize 属性注释的)页面时,他应该先登录或注册。

  2. 为了注册,他应该被重定向到一个帐户控制器,您应该在其中创建一个新用户,并将其添加到数据库中(您说您“将 AspNetCore.Identity 集成到其中”),这很好.. .and 应该用于验证和验证用户的身份。您的帐户控制器还应生成一个 Jwt 令牌,该令牌应传递给客户端应用程序,并存储在本地存储中。

  3. 现在,每当您的用户尝试访问 Web Api 端点上的受保护资源时,您应该从本地存储中检索 Jwt 令牌,并将其添加到请求标头中。如果您这样做,未经授权的响应将成为过去。

  4. 自定义 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,它定义了一个名为 GetTokenAsync 的方法,该方法提供(从本地存储读取 Jwt Token 并将其传递给调用代码)Jwt Token

希望这会有所帮助...

【讨论】:

  • 感谢您的回复!这对我帮助很大,我将它添加到我客户的自定义 AuthenticationProvider 中。现在授权正在工作:-)我现在面临的另一个问题是httpContextAccessor,试图在我面临SystemNullReferenceExceptions的控制器中获取usersId
  • 在 stackoverflow 中感谢人们的方式是投票并接受他们的答案。没有看到代码,我无法回答你的问题。请发布代码...
猜你喜欢
  • 2021-02-08
  • 1970-01-01
  • 1970-01-01
  • 2021-03-08
  • 2019-01-06
  • 2011-03-06
  • 2018-05-19
  • 2020-06-11
  • 2017-02-22
相关资源
最近更新 更多