c# - Blazor WebAssembly 401 未经授权,即使我已获得授权

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

我正在使用 Blazor WebAssembly Asp.Net Core 托管 PWA 并将 AspNetCore.Identity 集成到其中。我在客户端创建了 AuthenticationStateProvider,现在我想允许用户访问他需要获得授权的 Controller 。

我已经通过 postman 进行了测试,用户已创建并作为 aspnetusers 使用正确的凭据存储在数据库中。登录/帐户 Controller 按照我的意愿工作。

当用户获得授权时,它会在访问授权 Controller 请求时在浏览器中告知此异常:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Response status code does not indicate success: 401 (Unauthorized). System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized).

Startup.cs(ConfigureServices-方法):

...
    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();
            }

我的具有授权属性的 Controller :


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

最佳答案

注意:

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

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

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

  4. 自定义 AuthenticationStateProvider 是一个很好的地方,您可以从中管理将 Jwt token 存储在本地存储中并检索它以进行出站 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

希望这有助于...

关于c# - Blazor WebAssembly 401 未经授权,即使我已获得授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62841969/

相关文章:

c# - 以编程方式创建 SQL Server 表

c# - 有什么方法可以将迭代的 id 传递给 jquery?

c# - 单击时禁用 ASP.NET Core 按钮

c# - ASP.NET MVC4 实体验证错误 : User name already taken

c# - 当我在方法中使用变量时,可以将变量调用为方法的参数吗?

c# - TFS 客户端 API - 查询以获取链接到特定文件的工作项?

c# - 返回子类而不是父类(super class) F#

c# - 我如何在 AspNet.Core 中读取 EXIF 数据

c# - User.IsInRole() 返回 false 并且授权角色给我拒绝访问

asp.net - 使用asp.net core身份将数据存储在cookie中