我当前的身份验证过程如下所示。我有一个Auth API,可以使用UseOAuthBearerAuthentication
生成令牌。在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);
如果我查看Identity
中的当前OAuthTokenEndpointResponseContext context
上下文,Identity.Name
已设置,那么它应该使用此名称生成XSRF
令牌。 但是 HttpContext.Current.User.Identity
是null
在我的两个API中我也设置了
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimsIdentity.DefaultNameClaimType;
现在在我的Resource API中,我已经处理了从cookie中读取auth令牌并将其设置为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");
}
}
}
检查Identity
中的actionContext
,一切都已设置且用户已通过身份验证。但是,AntiForgery.Validate(cookieToken, formToken);
会抛出异常,如下所示。我看了很多其他的例子,但我找不到解决方案。
System.Web.Mvc.HttpAntiForgeryException:'提供的防伪 令牌适用于与当前用户不同的基于声明的用户 用户'。
编辑:因此,我似乎在XSRF
生成TokenEndpointResponse(OAuthTokenEndpointResponseContext context)
令牌的位置
context.Identity是使用经过身份验证的User
设置的,但HttpContext.Current.User
是null
。尽管此处生成的XSRF
令牌在技术上是有效的,但我认为它们使用HttpContext
中的空值。如果我使用[授权]生成XSRF
令牌是单独的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;
}
它有效!但它很难看,我想要一种更优雅的方式。
答案 0 :(得分:0)
这应该可以解决您的问题:
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.");
}