在 Asp.Net Core 3.1 Web Api 中使用面向方面编程检查用户授权

Check User Authorization with Aspect Oriented Programming in Asp.Net Core 3.1 Web Api

我想在 api 方法中检查用户授权。

负责通过 id 获取员工的方法。因此,如果用户与员工在同一家公司工作,则用户应呈现此方法。所以我的意思是用户 CompanyId 应该与 Employee CompanyId 相同。

这样想api方法:

    public async Task<IActionResult> GetEmployeeById([FromRoute]int id)
    {
        try
        {   
            var entity = await _employeeRepository.GetAsync(p => p.Id == id);
            if (entity == null)
            {
                return NotFound();
            }

            //user's CompanyId should be same with Employee CompanyId
            var user = await _userManager.FindByIdAsync(User.Identity.Name);

            if (user.CompanyId != eployee.CompanyId)
            {
                return Unauthorized();
            }

            return Ok(entity);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

我必须在所有 api 方法中检查用户公司。 所以我想通过Aspect Oriented Programming.So方法来做到这一点在AOP实现之后应该是这样的:

 [CheckUserCompany]
 public async Task<IActionResult> GetEmployeeById([FromRoute]int id)
    {
        try
        {   
            var entity = await _employeeRepository.GetAsync(p => p.Id == id);
            if (entity == null)
            {
                return NotFound();
            }

            return Ok(entity);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

如何在 Asp.Net Core 3.1 Web Api 中使用面向方面的编程来做到这一点?

谢谢

您可以像下面这样自定义一个 ActionFilter:

 public class CheckUserCompany:IActionFilter
{
    private readonly ApplicationDbContext _dbcontext;
    private readonly UserManager<ApplicationUser> _userManager;
    public CheckUserCompany(ApplicationDbContext dbcontext, UserManager<ApplicationUser> userManager)
    {
        _dbcontext = dbcontext;
        _userManager = userManager;
    }

    // Do something before the action executes.
    public void OnActionExecuting(ActionExecutingContext context)
    {
        var id = (int)context.ActionArguments["id"];
        var employee = _dbcontext.Employee.Find(id);
        var user = _userManager.FindByNameAsync(context.HttpContext.User.Identity.Name);

        if (user.Result.CompanyId != employee.CompanyId)
        {
            throw new UnauthorizedAccessException();
        }
        return;
    }

    // Do something after the action executes.
    public void OnActionExecuted(ActionExecutedContext context)
    {
    }
}

如果我们想将过滤器用作 Action 或 Controller 级别的服务类型,我们需要在相同的 ConfigureServices 方法中将其注册为 IoC 容器中的服务:

services.AddScoped<CheckUserCompany>();

最后,要使用在 Action 或 Controller 级别注册的过滤器,我们需要将其作为 ServiceType 放置在 Controller 或 Action 之上:

[ServiceFilter(typeof(CheckUserCompany))]
public async Task<IActionResult> GetEmployeeById([FromRoute]int id)