【发布时间】:2018-08-01 08:37:35
【问题描述】:
我当前的身份验证过程如下所示。我有一个使用UseOAuthBearerAuthentication 生成令牌的Auth API。在GrantResourceOwnerCredentials 中生成令牌后,我将Identity.Name 设置为identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName));
我想将我的令牌存储在 HttpOnly cookie 中,所以在 TokenEndpointResponse(OAuthTokenEndpointResponseContext context)
我将它保存到一个 cookie 中,但我还需要阻止 XSRF,所以我也在那里生成了一个 XSRF 令牌。
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
如果我从OAuthTokenEndpointResponseContext context 查看当前的Identity 上下文,Identity.Name 已设置,因此它应该使用此名称生成XSRF 令牌。 但是 HttpContext.Current.User.Identity 是 null 在我的两个 API 中我也设置了
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimsIdentity.DefaultNameClaimType;
现在,在我的资源 API 中,我已经从 cookie 中读取身份验证令牌并将其设置为 Authorization 标头。这很好用。然后我创建了我自己的XSRF 属性来验证XSRF 令牌。
public class ValidateAntiForgery : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
try
{
string cookieToken = "";
string formToken = "";
IEnumerable<string> tokenHeaders;
if (actionContext.Request.Headers.TryGetValues("X-XSRF-TOKEN", out tokenHeaders))
{
string[] tokens = tokenHeaders.First().Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
AntiForgery.Validate(cookieToken, formToken);
}
catch(Exception e)
{
actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Bad Request");
}
}
}
检查actionContext 中的Identity,一切都设置好了,用户也通过了身份验证。但是,AntiForgery.Validate(cookieToken, formToken); 会引发异常,如下所示。我查看了许多其他示例,但找不到解决方案。
System.Web.Mvc.HttpAntiForgeryException: '提供的防伪 令牌适用于与当前不同的基于声明的用户 用户。'
编辑:所以看来我在TokenEndpointResponse(OAuthTokenEndpointResponseContext context) 中生成我的XSRF 令牌
context.Identity 使用经过身份验证的User 设置,但是HttpContext.Current.User 是null。尽管此处生成的 XSRF 令牌在技术上是有效的,但我认为它们使用的是来自 HttpContext 的 null。如果我生成 XSRF 令牌是一个单独的带有 [Authorize] 的 GET 请求,因此 HttpContext.Current.User 不是 null,那么 AntiForgery.Validate 工作正常。
我希望XSRF 令牌与身份验证令牌一起返回,但我不知道该怎么做。如何设置HttpContext.Current.User.Identity?
编辑 2: 所以我能够使用 hacky 方式解决问题。当我想生成XSRF 令牌时,我调用以下函数。
[Authorize]
public string generateXSRFToken(ClaimsIdentity identity)
{
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(identity, new string[0]);
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
它有效!但它很难看,我想要一个更优雅的方式。
【问题讨论】:
标签: security asp.net-identity owin csrf claims-based-identity