authentication - Blazor 服务器无法访问具有 [Authorize] 属性的 Controller

标签 authentication asp.net-core model-view-controller blazor blazor-server-side

我刚接触网站,所以这可能有点幼稚。从基本的 Blazor Server (blazorserver) 模板开始,使用个人用户帐户进行身份验证,我在我的 Blazor 应用程序中添加了一个 DefaultControllerProject> Add Controller,然后选择一个具有读/写操作的 API Controller 。

然后我添加了 NuGet 包 Microsoft.AspNetCore.Blazor.HttpClient 并添加到 Startup.cs:

services.AddScoped<HttpClient>();

我还将 HttpClientNavigationManager 注入(inject)到 FetchData.razor 页面中。然后,我向我的 FetchData.razor 页面添加了一个按钮和功能:

<button @onclick="@TryIt">Try It</button>
private async Task TryIt()
{
    var x = await httpClient.GetJsonAsync<List<string>>($"{navigationManager.BaseUri}api/Default");
}

我运行该站点并单击尝试 按钮,它工作正常:我看到了列表中的两个项目。太棒了!

然后我将 [Authorize] 属性添加到 Controller 中的 HttpGet() 操作:

// GET: api/Default
[HttpGet]
[Authorize]
public IEnumerable<string> Get()
{
    return new string[] { "value1", "value2" };
}

当我再次运行该站点并单击尝试 时,没有任何乐趣(未处理的异常)。好的,也许我需要登录?运行站点,登录(在创建数据库并注册用户后)并单击试用。同样,我在控制台中遇到了可怕的异常:

Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer: Warning: Unhandled exception rendering component: '<' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.

System.Text.Json.JsonException: '<' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
 ---> System.Text.Json.JsonReaderException: '<' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.
   at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
   at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker)
   at System.Text.Json.Utf8JsonReader.ReadFirstToken(Byte first)
   at System.Text.Json.Utf8JsonReader.ReadSingleSegment()
   at System.Text.Json.Utf8JsonReader.Read()
   at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
   --- End of inner exception stack trace ---
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& readStack, JsonReaderException ex)
   at System.Text.Json.JsonSerializer.ReadCore(JsonSerializerOptions options, Utf8JsonReader& reader, ReadStack& readStack)
   at System.Text.Json.JsonSerializer.ReadCore(Type returnType, JsonSerializerOptions options, Utf8JsonReader& reader)
   at System.Text.Json.JsonSerializer.Deserialize(String json, Type returnType, JsonSerializerOptions options)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
   at Microsoft.AspNetCore.Components.HttpClientJsonExtensions.GetJsonAsync[T](HttpClient httpClient, String requestUri)
   at BlazorApp.Pages.FetchData.TryIt() in E:\DLS\Sandbox7\BlazorAppSolution\BlazorApp\Pages\FetchData.razor:line 57
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle)
Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost: Error: Unhandled exception in circuit 'H-xRrymKJQEov3vkCpOcExCeuUA2S2b1e15y6QSjxvw'.

我一直在阅读,为此我可能需要向 HTTP 请求添加 token ,但我不知道如何获取 token 。我在正确的轨道上吗?我需要添加什么?我错过了什么?

由于我对这方面真的很陌生,我可以使用尽可能多的指导,尽可能多地提供详细信息。

最佳答案

首先,引发异常是因为 JsonSerializer 无法反序列化传递给它的内容。它期望获得可以反序列化为 List 的 JSON,但从服务器获得了一条消息,报告发生了错误。此消息以 HTML 格式提供。

不应在 Blazor Server 应用程序中使用 Microsoft.AspNetCore.Blazor.HttpClient。它旨在用于 Blazor WebAssembly 应用程序。使用 IHttpClientFactory 在服务器端 Blazor 中使用 HttpClient 服务。

使用具有个人用户帐户的模板进行身份验证意味着您的用户通过 Asp.Net Core 身份系统 (IdentityUI) 进行身份验证,包括数据库、模型等。IdentityUI 附带的所有好东西。但这仅与身份验证有关。

现在,如果你想访问 Web Api 端点,并希望通过使用 Authorize 属性装饰它们来保护这些端点,你需要使用授权系统,例如 OpenID Connect 等。

首先,我建议您使用 JWT token 身份验证来向经过身份验证的用户颁发 JWT token 。您可以将 Controller 专用于验证用户的任务,创建包含有关用户的各种声明的 JWT token 。此 JWT token 仅在用户通过身份验证后创建一次,并将其传递给调用代码(您的 Blazor 服务器应用程序),该代码应将其存储在本地存储(JavaScript 本地存储)中。现在,每当您想从安全的 Web Api 端点检索给定用户的数据时,您应该从本地存储读取 Jwt token ,并将其添加到 HTTP 请求的授权 header 。下面是一个演示如何在 Authorization header 中传递 Jwt Token 的 HTTP 请求。注意:这是使用您添加的包完成的,不建议将其与服务器端 Blazor 一起使用。您可能会暂时使用它,但在一天结束时,您应该转移到 IHttpClientFactory。

@code {
User[] users;

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

注意:这个主题非常全面,我建议您使用文档来了解它的基础知识。还有我和其他人关于身份验证和授权的答案,您可以从中学到很多东西。学习使用 Blazor 中与授权相关的组件和对象也很重要。

希望这有助于...

关于authentication - Blazor 服务器无法访问具有 [Authorize] 属性的 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60999733/

相关文章:

c# - ASP.Net Core 中的全局异常处理程序(非 UI)

javascript - 在另一个 ViewComponent 中调用一个 ViewComponent

java - View 应该负责停止和开始在MVC中监听模型吗?

php - Ajax 登录和 javascript cookie,这安全吗?

iOS:在设备上永久存储身份验证数据

http - 使用 OWIN 添加多个 WWW-Authenticate header

ios - Objective-C:具有一种模型和多种 View Controller 的 MVC

django - 如何让 NGINX/Django 检测何时删除了 CAC/智能卡?

c# - 在 ASP.NET Core 中手动绑定(bind)表单数据

angularjs - 在 AngularJS 中将业务逻辑与 Controller 分离