如何编写异步策略处理程序,注入范围服务
Posted
技术标签:
【中文标题】如何编写异步策略处理程序,注入范围服务【英文标题】:How to write an asynchronous Policy handler, injecting a scoped service 【发布时间】:2020-05-28 09:12:47 【问题描述】:我正在尝试使用自定义身份存储提供程序为 ASP.NET Core 3.1 Web 应用程序编写自定义策略。
当我在MSDN Article 中读到这篇文章时,我试图理解 ASP.NET Core 中的策略旨在从 HttpContext
对象中获取用户信息这一事实:
一旦您持有对用户的引用,您始终可以从声明中找到用户名,并对任何数据库或外部服务运行查询
我开始编写自己的策略(目前是一个简单的角色要求),将UserManager
注入构造函数:
public class RoleHandler : AuthorizationHandler<RoleRequirement>
private UserManager<AppUser> UserManager;
public RoleHandler(UserManager<AppUser> usermanager)
UserManager = usermanager;
现在我有几个问题:
在单例中注入作用域服务
策略应该在整个应用程序生命周期内持续存在,所以这将是一个单例:
services.AddSingleton<IAuthorizationHandler, RoleHandler>();
但注入策略服务器的 UserManager 是一个范围服务,这是不允许的。解决方案非常简单,将策略服务的配置从单例更改为范围服务
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就这样写 await Task.CompletedTask;你为什么不像这样使用 context.User.IsInRole(requirement.Role.ToString()) @Muhammad Sami context.User 没有公开 IsInRole 方法,这是一个完全不同的实体。 【参考方案1】:不要返回Task.CompletedTask
。
当您将方法声明为async
时,它隐式在第一个await
被命中时返回Task
:
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
返回方法的时候,你不需要。
【讨论】:
以上是关于如何编写异步策略处理程序,注入范围服务的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Express 请求处理程序中编写非阻塞异步函数 [重复]