我当前的身份验证过程看起来像这样。我有一个用UseOAuthBearerAuthentication
生成令牌的authapi。在GrantResourceOwnerCredentials
内生成令牌后,我将Identity.Name
设置CC_3
我想将令牌存储在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
是我的两个API中的null
,我也设置了
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
代币是一个单独的GET
请求,则使用[授权],以便HttpContext.Current.User
不是null
,则AntiForgery.Validate
可以正常工作。
我希望使用身份验证令牌返回XSRF
令牌,但我不确定该怎么做。如何设置HttpContext.Current.User.Identity
?
编辑2:,因此我能够使用骇人听闻的方式来解决问题。当我想生成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;
}
它有效!
这应该解决您的问题:
var returnUrl = Request.QueryString["ReturnUrl"];
if (returnUrl.IsEmpty()) {
// Some external login providers always require a return URL value
returnUrl = Href("~/");
}
if (WebSecurity.Login(email, password, rememberMe))
{
Context.RedirectLocal(returnUrl);
return;
}
else
{
ModelState.AddFormError("The user name or password provided is incorrect.");
}