【发布时间】:2021-07-26 15:48:02
【问题描述】:
上下文
我有一个带有多个控制器的 ASP.NET Core MVC 应用程序(仅返回视图)。该应用已使用 ASP.NET Core Identity 进行身份验证和授权。但是,有几个地方我需要使用 HTTP 客户端直接调用控制器操作端点作为 API。看来这需要 Identity 似乎不支持开箱即用的 API 身份验证。
问题
我需要使用 component tag helper(渲染模式为 ServerPrerendered)从嵌入到我的 MVC 视图中的 Razor 组件调用这些控制器操作。
现在,我可以直接从我的 Razor 组件访问我的数据库,方法是将数据库服务注入到我的组件中,就像我对其他 Razor 组件所做的那样。但是,我不能用这个 Razor 组件来做到这一点,因为它需要访问 Identity 的 UserManager 服务并且根据 documentation:
Razor 组件不支持
SignInManager<TUser>和UserManager<TUser>。 Blazor 服务器应用使用 ASP.NET Core 标识。
因此,我似乎必须通过注入 IHttpClientFactory 从我的 Razor 组件调用控制器操作。
但是,到目前为止,在我的整个应用程序中,我只需要为两个操作调用控制器操作:
- 用于创建用户
- 用于编辑用户
您可能会问为什么我需要 Razor 组件来创建用户帐户。创建帐户是一个相当复杂的步骤(多个步骤),涉及客户端交互,例如将项目动态添加到列表中。 Razor 组件让我变得如此简单。如果我在 .cshtml 视图中这样做,我将不得不使用 JavaScript/jQuery。
目标
我不认为仅仅为了帮助我完成这两个操作而创建一个完整的 API 项目是值得的(尽管我不介意这样做)。我可以将这些操作添加到我现有的帐户控制器或在同一个项目中创建一个新的 API 控制器。 尽管如此,我仍然必须保护这些端点。
主要问题
如何向这两个控制器操作(创建用户和编辑用户)添加 API 身份验证和授权,而不影响现有的 ASP.NET Core 身份设置正在执行的操作?
我仍然希望我的应用程序中的其余控制器使用相同的身份验证/授权,但这些 Create 和 Edit 用户操作的 API 身份验证/授权。
或者由于我的 Razor 组件嵌入在 MVC 视图中,有没有办法通过我的组件调用控制器操作,就像 MVC 视图通过发送带有请求的 cookie 一样?
无论如何,我的目标是保护两个控制器操作端点。
代码
这是Startup.cs中当前配置身份的方式:
services.AddDefaultIdentity<AppUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<AppDbContext>();
这是我的Create 控制器操作的简化版本:
[Authorize(Roles = "Administrator")]
public async Task<IActionResult> Create(UserViewModel model)
{
if (ModelState.IsValid)
{
AppUser user = model.ToAppUser(); // Method on view model does the mapping
user.Id = Guid.NewGuid().ToString();
IdentityResult createUserResult = await _userManager.CreateAsync(user, model.Password);
if (createUserResult.Succeeded)
{
await userManager.AddToRoleAsync(user, role.Name);
return Ok();
}
foreach(var error in createUserResult.Errors)
{
ModelState.AddModelError("", error.Description);
}
}
}
这就是我从 Razor 组件调用它的方式:
CreateUser.razor:
@inject IHttpClientFactory HttpClientFactory
<EditForm Model="_model" OnValidSubmit="HandleValidSubmit">
...
</EditForm>
@code {
private UserViewModel _model = new();
public async Task HandleValidSubmit()
{
var modelAsJson = new StringContent(
JsonSerializer.Serialize(_model),
Encoding.UTF8,
"application/json");
using var httpResponse =
await _httpClient.PostAsync("/api/Accounts/Create", modelAsJson);
//...
}
}
使用 <component> 将组件嵌入到 MVC 视图中:
Create.cshtml
...
<component type="typeof(CreateUser)" render-mode="ServerPrerendered" />
更新
经过一些研究,我发现 JWT 是最常用的 API 身份验证方式。根据here 的说明,这是在Startup.cs 中添加的方式:
services.AddAuthentication( auth =>
{
auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options => {..})
这里,当默认身份验证方案设置为 JWT 时,这会覆盖我的默认身份设置吗?如何同时使用这两种方案?
【问题讨论】:
-
创建一个 API。如果不是,那么调用该控制器的用户必须在点击控制器之前通过身份登录。您必须使用 OIDC 客户端在客户端实现某种类型的静默登录,这对我来说比连接 API 更令人头疼。更不用说您将带来的安全漏洞,例如跨站点脚本。
标签: c# asp.net asp.net-core authentication blazor