我试图为一个ASP.NET Core 3.1网络应用程序编写一个自定义策略,使用一个自定义身份存储提供商。
我试着去理解ASP.NET Core中的策略被设计成从用户信息中获取用户信息。HttpContext
对象,当我在 MSDN文章:
一旦你持有对用户的引用,你可以随时从索赔中找到用户名,并对任何数据库或外部服务进行查询。
我开始写自己的策略(就像现在简单的角色需求)注入了 UserManager
到构造函数中。
public class RoleHandler : AuthorizationHandler<RoleRequirement>
{
private UserManager<AppUser> UserManager;
public RoleHandler(UserManager<AppUser> usermanager)
{
UserManager = usermanager;
}
}
现在我有几个问题
INJECTING A SCOPED SERVICE IN A SINGLETON.
策略应该是在整个应用生命中持续存在的,所以这应该是一个Singleton。
services.AddSingleton<IAuthorizationHandler, RoleHandler>();
但在策略服务器中注入的UserManager是一个scoped服务,这是不允许的。解决方法很简单,把策略服务的配置从单人服务改成了范围服务
services.AddScoped<IAuthorizationHandler, RoleHandler>();
但我不知道这是否会引起任何问题。
编写一个动态策略处理程序。
这是我对 HandleRequirementAsync
方法。
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
{
AppUser user = UserManager.FindByIdAsync(context.User.Identity.Name).Result;
if (user != null)
{
bool result = UserManager.IsInRoleAsync(user, requirement.Role.ToString()).Result;
if (result) context.Succeed(requirement);
}
return Task.CompletedTask;
}
我用的是 Task.Result
但它阻止了线程。我不能用 await
因为这将使该方法返回一个 Task<Task>
而非 Task
而我却无法改变它。我如何解决这个问题?
不要返回 Task.CompletedTask
.
当你把一个方法声明为 async
,它 隐性 返回一个 Task
当初 await
是打。
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
{
AppUser user = await UserManager.FindByIdAsync(context.User.Identity.Name);
if (user != null)
{
bool result = await UserManager.IsInRoleAsync(user, requirement.Role.ToString());
if (result) context.Succeed(requirement);
}
}
Task.CompletedTask
一般用于当你需要实现一个 Task
同步返回方法,而你不是。