在 .net core 1.1 中访问 Action 方法之前,如何在控制器 属性 上设置用户?

How to set User on controller property before Action method is accessed in .net core 1.1?

使用 .net 核心 1.1 mvc

objective是限制用户只能自己编辑,或者允许管理员编辑用户。我需要获取当前用户并将该用户的 ID 与参数(或 cookie)中传递的用户 ID 进行比较。

如果用户 ID 不匹配,请检查当前用户是否为管理员。如果是这样,获取作为参数(或 cookie)传入的用户 ID 的用户。

我们有一个控制器,它通过依赖注入在构造函数中接收 ApplicationDBContext 和 UserManager。

我两次尝试都失败了: 1) 我尝试创建一个 ActionFilter,它通过 context.Controller.UserManager(我从控制器构造函数设置的 属性)访问 UserManager,但是 UserManager 有一个 IDisposable 错误。

2) 我尝试从 Controller 构造函数执行此操作,但如果找不到用户并且不知道如何从 Action 方法外部执行此操作,我需要将响应设置为 404。

经过一天的反复试验,我弄明白了,想分享一下,因为我在网上找不到任何例子。

请注意,我必须使用 IAsyncActionFilter,因为一旦我在过滤器中调用异步方法,代码就会在 Action 方法中开始执行 (Controller.UserToEditProp = await UserManager.FindByIdAsync)

public class ImpersonateAttribute : ActionFilterAttribute, IAsyncActionFilter
{
    public override async Task OnActionExecutionAsync(
        ActionExecutingContext context,
        ActionExecutionDelegate next)
    {
        string ThisUserID = context.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
        ApiController Controller = (ApiController)context.Controller;
        var UserManager = Controller.UserManager;

        if (context.ActionArguments.ContainsKey("UserID"))
        {
            string RequestedUserID = context.ActionArguments["UserID"].ToString();

            if (ThisUserID != RequestedUserID)
            {
                if (!context.HttpContext.User.IsInRole(UserType.Admin.GetDisplayName()))
                {
                    context.Result = new UnauthorizedResult();
                }
            }

            Controller.UserToEditProp = await UserManager.FindByIdAsync(RequestedUserID);
        }
        else
        {
            Controller.UserToEditProp = await UserManager.FindByIdAsync(ThisUserID);
        }

        await next();

        // do something after the action executes
    }

}