如何编写异步策略处理程序,注入范围服务

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&lt;Task&gt; 而不是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 请求处理程序中编写非阻塞异步函数 [重复]

如何编写优雅的异步代码 — CompletableFuture

如何编写客户端代码以允许记录器注入

如何使事件处理程序异步运行?

多线程编程学习笔记——编写一个异步的HTTP服务器和客户端

如何为 Node.js 编写异步函数