ASP.net Identity send AntiForgeryToken from javascript



ASP.net MVC 5提供了帐户控制器和帐户视图。在Register(寄存器)视图中有一行

@Html.AntiForgeryToken()

在寄存器控制器上面有一个属性:

[ValidateAntiForgeryToken]

我决定使用JSON从javascript向服务器发送数据(我使用Angular和$http.post方法)。

我的问题是如何使用javascript发送这个AntiForgeryToken并在控制器中验证它?

还有什么我应该包括的安全措施吗?

AngularJS内置支持XSRF(又名防伪)

XSRF是一种未经授权的网站可以获得用户私人数据。Angular提供了一种对抗XSRF的机制。什么时候执行XHR请求时,$http服务从cookie中读取令牌(默认情况下,XSRF-TOKEN),并将其设置为HTTP标头(X-XSRF-TOKEN)。由于只有在您的域上运行的JavaScript才能读取cookie,您的服务器可以确信XHR来自运行的JavaScript在您的域上。不会为跨域请求设置标头。

如果你想利用这个功能,你必须创建操作过滤器来创建和验证XSRF-TOKEN cookie。这是我使用的简化版本。

AntiForgeryTokenCookieAttribute-使用此属性添加XSRF-TOKEN cookie

/// <summary>
/// Create a XSRF token in the XSRF-TOKEN cookie which is automatically read by AngularJS
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class AntiForgeryTokenCookieAttribute : ActionFilterAttribute
{
    private readonly IAntiForgeryVerificationTokenStore _verificationTokenStore = new AntiForgeryVerificationTokenCookieStore(); //TODO: make configurable
    private const string CookieName = "XSRF-TOKEN"; //TODO: make configurable
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        var oldVerificationToken = _verificationTokenStore.GetVerificationToken(filterContext.HttpContext.Request);
        string newVerificationToken;
        string newToken;
        AntiForgery.GetTokens(oldVerificationToken, out newVerificationToken, out newToken);
        if (newVerificationToken != null)
        {
            _verificationTokenStore.StoreVerificationToken(filterContext.HttpContext.Response, newVerificationToken);
        }
        filterContext.HttpContext.Response.Cookies.Add(new HttpCookie(CookieName, newToken));
    }
}

ValidateAntiForgeryTokenHeaderAttribute

/// <summary>
/// Validate the XSRF token stored in the X-XSRF-TOKEN header.
/// If the header doesn't exist, look for the XSRF token in the from post.
/// 
/// Compatible with ValidateAntiForgeryTokenAttribute
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class ValidateAntiForgeryTokenHeaderAttribute : FilterAttribute, IAuthorizationFilter
{
    private readonly IAntiForgeryVerificationTokenStore _verificationTokenStore = new AntiForgeryVerificationTokenCookieStore(); //TODO: make configurable
    private const string TokenHeaderName = "X-XSRF-TOKEN"; //TODO: make configurable
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var token = filterContext.HttpContext.Request.Headers[TokenHeaderName];
        if (token != null)
        {
            //validate the token stored in header
            var verificationToken = _verificationTokenStore.GetVerificationToken(filterContext.HttpContext.Request);
            if (verificationToken == null) { throw new HttpAntiForgeryException("Required verification token not found"); }
            AntiForgery.Validate(verificationToken, token);
        }
        else
        {
            //validate the token stored in form. Same as ValidateAntiForgeryTokenAttribute
            AntiForgery.Validate();
        }
    }
}

IAntiForgeryVerificationTokenStore

public interface IAntiForgeryVerificationTokenStore
{
    string GetVerificationToken(HttpRequestBase request);
    void StoreVerificationToken(HttpResponseBase response, string token);
}

AntiForgeryVerificationTokenCookiesStore

public class AntiForgeryVerificationTokenCookieStore : IAntiForgeryVerificationTokenStore
{
    public string GetVerificationToken(HttpRequestBase request)
    {
        if (request == null) { throw new ArgumentNullException("request"); }
        var token = request.Cookies[AntiForgeryConfig.CookieName];
        return token != null ? token.Value : null;
    }
    public void StoreVerificationToken(HttpResponseBase response, string token)
    {
        if (response == null) { throw new ArgumentNullException("response"); }
        if (token == null) { throw new ArgumentNullException("token"); }
        response.Cookies.Add(new HttpCookie(AntiForgeryConfig.CookieName, token) { HttpOnly = true, Secure = AntiForgeryConfig.RequireSsl });
    }
}

相关内容

  • 没有找到相关文章

最新更新