[英]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:笔记:
When your user tries to access a protected (annotated with the Authorize attribute) page on the client he should login first or register.当您的用户尝试访问客户端上受保护的(使用 Authorize 属性注释的)页面时,他应该首先登录或注册。
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 令牌,该令牌应该传递给客户端应用程序,并存储在本地存储中。
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.
如果您这样做,未经授权的响应将成为过去。
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.