简体   繁体   English

Blazor WebAssembly 401 未经授权,即使我被授权

[英]Blazor WebAssembly 401 Unauthorized even when I am authorized

I am using Blazor WebAssembly Asp.Net Core hosted PWA and integrated the AspNetCore.Identity into it.我正在使用Blazor WebAssembly Asp.Net Core hosted PWA并将AspNetCore.Identity集成到其中。 I created the AuthenticationStateProvider in the Client-Side and now I want to allow the user access to a controller where he needs to be authorized.我在客户端创建了AuthenticationStateProvider ,现在我想允许用户访问需要授权的 controller。

I have tested via postman, the users were been created and stored in DB as aspnetusers with the right credentials.我已经通过 postman 进行了测试,用户已创建并作为具有正确凭据的aspnetusers存储在数据库中。 The Login/Account Controller work as I wanted it.登录/帐户 Controller 按我的意愿工作。

When the user is authorized it tells this exception in the browser when accessing the authorized controller request:当用户获得授权时,它会在访问授权的 controller 请求时在浏览器中显示此异常:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Response status code does not indicate success: 401 (Unauthorized). Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] 未处理的异常渲染组件:响应状态码不表示成功:401(未授权)。 System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized). System.Net.Http.HttpRequestException:响应状态码不表示成功:401(未授权)。

Startup.cs ( ConfigureServices -Method): 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 Client-Side 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();
            }

My Controller with authorize attribute:我的 Controller 具有授权属性:


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

Note:笔记:

  1. When your user tries to access a protected (annotated with the Authorize attribute) page on the client he should login first or register.当您的用户尝试访问客户端上受保护的(使用 Authorize 属性注释的)页面时,他应该首先登录或注册。

  2. In order to register, he should be redirected to an Account Controller where you should create a new user, and add it to the database (You said you " integrated the AspNetCore.Identity into it"), which is fine...and should be used to authenticate and verify the user's identity.为了注册,他应该被重定向到一个帐户 Controller,您应该在其中创建一个新用户,并将其添加到数据库中(您说您“将 AspNetCore.Identity 集成到其中”),这很好......应该用于验证和验证用户的身份。 You account controller should also produce a Jwt Token that should be passed to the client app, and stored in the local storage.您的帐户 controller 还应该生成一个 Jwt 令牌,该令牌应该传递给客户端应用程序,并存储在本地存储中。

  3. Now, whenever your user tries to access protected resources on your Web Api endpoints, you should retrieve the Jwt Token from the local storage, and add it to the request header. Now, whenever your user tries to access protected resources on your Web Api endpoints, you should retrieve the Jwt Token from the local storage, and add it to the request header. If you do so, the Unauthorized response would be something of the past.如果您这样做,未经授权的响应将成为过去。

  4. Custom AuthenticationStateProvider can be a good place from which you can manage storing the Jwt Token in the local storage and retrieving it for outbound HTTP request calls.自定义 AuthenticationStateProvider 可以是一个好地方,您可以从中管理将 Jwt 令牌存储在本地存储中,并为出站 HTTP 请求调用检索它。

Here's some sample code to clarify what you should do:这里有一些示例代码来阐明你应该做什么:

@code {
    WeatherForecast[] forecasts;

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

Note: TokenProvider is a custom AuthenticationStateProvider that defines a method called GetTokenAsync that provides (reading the Jwt Token from the local storage and passing it to the calling code) the Jwt Token注意:TokenProvider 是一个自定义的 AuthenticationStateProvider,它定义了一个名为 GetTokenAsync 的方法,该方法提供(从本地存储读取 Jwt 令牌并将其传递给调用代码)Jwt 令牌

Hope this helps...希望这可以帮助...

In case of Linux App Service in combination with ID Server the Authority needs to be set according to Microsoft documentation: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-api-authorization?view=aspnetcore-5.0#azure-app-service-on-linux-1如果 Linux App Service 与 ID 服务器结合使用,则需要根据 Microsoft 文档设置授权: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-api-authorization?视图=aspnetcore-5.0#azure-app-service-on-linux-1

services.Configure<JwtBearerOptions>(
    IdentityServerJwtConstants.IdentityServerJwtBearerScheme, 
    options =>
    {
        options.Authority = "{AUTHORITY}";
    });

Example: options.Authority = "https://contoso-service.azurewebsites.net";示例: options.Authority = "https://contoso-service.azurewebsites.net";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我会收到 401 未经授权的响应? - Why Am I Getting 401 Unauthorized Response? 即使使用 ASP.NET CORE 登录,我在 Angular 中也有 401 Unauthorized - I have a 401 Unauthorized in Angular even when login whit ASP.NET CORE 将文件字节流发送到WCF服务时,为什么会出现“ 401-未经授权”错误? - Why am I getting a “401 - Unauthorized” error when sending a file byte stream to a WCF service? 将HttpResponseMessage与安全网址一起使用时,为什么会出现未经授权的401? - Why am I getting a 401 unauthorized when using HttpResponseMessage with a secure url? 为什么我会收到未经授权的Yahoo OAuth 2.0错误(401)? - Why i am getting Yahoo OAuth 2.0 error (401) Unauthorized? 为什么我在 Google Calendar API 中收到 (401) 未经授权的错误 - Why am I getting a (401) Unauthorized Error in Google Calendar API 当我部署 Blazor WebAssembly 时,API 停止响应 - When I deploy the Blazor WebAssembly, API stops responding Blazor WA 托管 - 401 在 Azure AppService 上未经授权 - Blazor WA hosted - 401 Unauthorized on Azure AppService 当用户在 Blazor 中未授权时,我想显示多个带有路由的页面 - I want to show multiple pages with routing when user is not Authorized in Blazor 未授权时总是返回 401 - When not authorized always return a 401
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM