ApiController覆盖以访问User.Claims

时间:2016-04-25 19:44:40

标签: c# model-view-controller asp.net-web-api asp.net-identity owin

我有一个基础api控制器,我从ApiController继承。在其中,我重写了ExecuteAsync并希望使用存储在Principal.Claims var中的一些数据。但在调用base.ExecuteAsync()之前它是空的,并且在调用它之后太晚了。我没有看到其他任何要覆盖的东西来帮助它吗?

public class ApiControllerBase : ApiController
{
    public MyUser CurrentUser { get; set; }

    public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
    {
        // principal.claims is empty
        ClaimsPrincipal principal = (ClaimsPrincipal)RequestContext.Principal; // principal.claims is empty

        var rv = base.ExecuteAsync(controllerContext, cancellationToken);

        // principal.claims is now populated but the controller.action that inherits from this basecontroller has already fired and thrown an exception since CurrentUser is null.
        principal = (ClaimsPrincipal)RequestContext.Principal;
    }
}

3 个答案:

答案 0 :(得分:2)

如果您需要访问控制器中的声明,您可以执行以下操作:

public class MyUser 
{
    private readonly ClaimsIdentity _identity;

    public SeaUser(ClaimsIdentity identity)
    {
        _identity= identity;
    }

    public IEnumerable<Claim> Claims { get { return _identity.Claims; } }
}

public abstract class BaseController : ApiController
{
    private MyUser _user;

    public new MyUser User
    {
        get 
        { 
            return _user ?? (_user = User.Identity != null 
                                  ? new MyUser((ClaimsIdentity)User.Identity) 
                                  : null); }
        }
    }
}

然后在任何需要的地方使用User属性。

假设请求进入ApiController范围,操作顺序如下:

  • 调用ApiController的ExecuteAsync方法。
  • 调用ApiController的Initialize方法。
  • 检索已注册的操作选择器。
  • 调用已注册的操作选择器的SelectAction方法。 如果只匹配一个操作方法,则管道继续。
  • 检索所选操作的所有已注册过滤器。
  • 调用授权过滤器。授权过滤器可以 决定让管道继续执行还是继续执行 终止管道。
  • 如果授权过滤器未终止请求,请执行操作 执行参数绑定。
  • 设置了ApiController.ModelState。
  • 动作过滤器被调用。动作过滤器决定要么 让管道继续执行或终止管道。
  • 如果Action Filters未终止请求,则注册Action 检索到Invoker。
  • 已注册的Action Invoker的InvokeActionAsync方法是 调用以调用所选的操作方法。

注意:如果从执行授权过滤器到执行操作方法发生任何异常,则会调用异常过滤器。

之间还会发生一些事情,但这非常接近完整视图。有关详细信息,请查看ApiController source code

答案 1 :(得分:0)

您可以覆盖OnActionExecuting(),每次执行操作时都会调用它。

public override void OnActionExecuting(ActionExecutingContext context)
    {
        var user = context.HttpContext.User;
        //store user.Claims in property so inherited controllers have access
        base.OnActionExecuting(context);
    }

答案 2 :(得分:0)

这对我有用(Thread.CurrentPrincipal)

SELECT DISTINCT u.department from User u (based on Department name)

我不确定IAppBuilder(Startup.Configuration)中的注册顺序是否重要,但我注册的第一件事是Authentication中间件。