ApiController 重写以访问 User.Claims
ApiController override to access User.Claims
我有一个从 ApiController 继承的基础 api 控制器。在其中,我覆盖了 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;
}
}
您可以覆盖 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);
}
如果您需要访问控制器中的声明,您可以执行以下操作:
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); }
}
}
}
然后在任何需要的地方使用用户 属性。
假设请求进入ApiController作用域,操作顺序如下:
- ApiController 的 ExecuteAsync 方法被调用。
- 调用了 ApiController 的 Initialize 方法。
- 检索到已注册的动作选择器。
- 已注册的动作选择器的 SelectAction 方法被调用。
如果只有一种操作方法匹配,则管道继续。
- 已检索所选操作的所有已注册过滤器。
- 已调用授权过滤器。授权过滤器可以
决定让管道继续执行或
终止管道。
- 如果授权过滤器没有终止请求,操作
执行参数绑定。
- ApiController.ModelState 已设置。
- 操作过滤器被调用。动作过滤器决定要么
让管道继续执行或终止管道。
- 如果 Action Filters 没有终止请求,则注册 Action
检索调用程序。
- 注册的Action Invoker的InvokeActionAsync方法是
调用以调用选定的操作方法。
注意:如果从执行Authorization Filters到执行action方法有任何异常发生,就会调用异常过滤器。
中间还发生了一些事情,但这非常接近完整视图。查看 ApiController source code 了解更多信息。
这对我有用 (Thread.CurrentPrincipal)
public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
var principal = Thread.CurrentPrincipal as ClaimsPrincipal;
return base.ExecuteAsync(controllerContext, cancellationToken);
}
我不确定在 IAppBuilder (Startup.Configuration) 中注册的顺序是否重要,但我首先注册的是身份验证中间件。
我有一个从 ApiController 继承的基础 api 控制器。在其中,我覆盖了 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;
}
}
您可以覆盖 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);
}
如果您需要访问控制器中的声明,您可以执行以下操作:
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); }
}
}
}
然后在任何需要的地方使用用户 属性。
假设请求进入ApiController作用域,操作顺序如下:
- ApiController 的 ExecuteAsync 方法被调用。
- 调用了 ApiController 的 Initialize 方法。
- 检索到已注册的动作选择器。
- 已注册的动作选择器的 SelectAction 方法被调用。 如果只有一种操作方法匹配,则管道继续。
- 已检索所选操作的所有已注册过滤器。
- 已调用授权过滤器。授权过滤器可以
决定让管道继续执行或 终止管道。 - 如果授权过滤器没有终止请求,操作 执行参数绑定。
- ApiController.ModelState 已设置。
- 操作过滤器被调用。动作过滤器决定要么 让管道继续执行或终止管道。
- 如果 Action Filters 没有终止请求,则注册 Action 检索调用程序。
- 注册的Action Invoker的InvokeActionAsync方法是 调用以调用选定的操作方法。
注意:如果从执行Authorization Filters到执行action方法有任何异常发生,就会调用异常过滤器。
中间还发生了一些事情,但这非常接近完整视图。查看 ApiController source code 了解更多信息。
这对我有用 (Thread.CurrentPrincipal)
public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
var principal = Thread.CurrentPrincipal as ClaimsPrincipal;
return base.ExecuteAsync(controllerContext, cancellationToken);
}
我不确定在 IAppBuilder (Startup.Configuration) 中注册的顺序是否重要,但我首先注册的是身份验证中间件。