编辑:我改变了我的方法。现在我正在使用消息处理程序。感谢 Raciel,他指出了挖掘的方向。
这些链接对我来说非常有用: MessageHandlers overview Using own Principal classes
<小时/>我有一个WebApi项目,需要为其提供自定义授权。特殊的 Token 对象被添加到前端的每个请求中。类似这样的事情:
SendApiRequest: function (controller, action, data, successCallback, failureCallback) {
var url = ROUTER.GetApiUrl(controller, action);
data.Token = TOKEN;
jQuery.ajax({
type: 'POST',
dataType: 'json',
url: url,
data: data,
success: function (result) {
if (typeof successCallback == 'function') {
successCallback(result);
}
},
error: function (result) {
if (typeof failureCallback == 'function') {
failureCallback(result);
}
}
});}
我有一个 AuthorizationAttribute,我需要以某种方式从请求中序列化 Token 对象。但找不到任何自动方法来做到这一点。
public class CustomAuthorizationAttribute : AuthorizeAttribute
{
public override void OnAuthorization(HttpActionContext context)
{
UserToken token = null;
//HOW TO SERIALIZE token object from context?
}
}
UserToken 类看起来像这样:
public class UserToken
{
public Int64 TokenID;
public int UserID;
public string TokenValue;
public string IP;
public string Hash;
public DateTime CreatedOn;
public DateTime ActionOn;
}
所以问题是:如何从 HttpActionContext 序列化自定义对象?
谢谢。
最佳答案
这就是我在处理与您类似的案例时所做的。
您可以创建一个 MessageHandler 来检查 token 并在每个请求时验证它,而不是创建自己的 Authorize 属性。此消息处理程序负责填充当前线程中的 Principal,因此 Authorize 属性可以按预期工作,允许授权客户端访问相关 Controller /操作。
这就是我的授权消息处理程序的样子:
public class AuthMessageHandler : DelegatingHandler
{
protected ITokenProvider TokenProvider { get; private set; }
protected IPrincipalProvider PrincipalProvider { get; private set; }
public AuthMessageHandler(ITokenProvider tokenProvider, IPrincipalProvider principalProvider)
{
TokenProvider = tokenProvider;
PrincipalProvider = principalProvider;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Identity identity = null;
string token = ExtractToken(request);
if (token != null && TokenProvider.Verify(token, out identity))
{
request.Properties.Add(Constants.IdentityKey, identity);
var principal = PrincipalProvider.CreatePrincipal(identity);
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
}
return base.SendAsync(request, cancellationToken);
}
private string ExtractToken(HttpRequestMessage request)
{
IEnumerable<string> tokenValues = null;
if (request.Headers.TryGetValues(Constants.TokenHeaderKey, out tokenValues))
return tokenValues.First();
return null;
}
}
请注意:
- TokenProvider和PrincipalProvider都在这里注入(inject)。第一个负责验证 token ,如果有效,则返回身份数据,以便在请求中可用。
- IPrincipal 提供程序只是创建一个 GenericPrincipal,然后将其分配给 Thread.CurrentPrincipal 和上下文用户 (HttpContext.Current.User)。这可以确保 Authorize 属性稍后在检查当前主体中的 IsAuthenticated 时起作用。
- 在本例中,我在 header 中传递 token 信息,这是我更喜欢的。 (您可能还需要授权 GET 请求)
- 如果您需要将数据从消息处理程序传递到 Controller ,则可以使用 request.Properties,这就是为什么我使用 request.Properties.Add(Constants.IdentityKey, Identity); 将身份信息放在那里的原因。所以它可供 Controller 使用。有多种方法可以实现此目的,但对于此类数据来说,此字典几乎是一种廉价的传输方式。
如果您有任何疑问,请告诉我。这实际上比看起来更简单。
关于c# - WebApi 从 HttpActionContext 序列化对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18322594/