javascript - ASP.net 身份从 javascript 发送 AntiForgeryToken

标签 javascript asp.net asp.net-mvc angularjs asp.net-identity

随着 ASP.net MVC 5 的出现,Account Controller 和 Account Views 也随之而来。在 Register View 中有行

@Html.AntiForgeryToken()

在注册 Controller 上面有属性:

[ValidateAntiForgeryToken]

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

我的问题是如何使用 javascript 发送此 AntiForgeryToken 并在 Controller 中对其进行验证?

还有我应该包括的更多安全措施吗?

最佳答案

AngularJS 内置了对 XSRF(又名防伪造)的支持

XSRF is a technique by which an unauthorized site can gain your user's private data. Angular provides a mechanism to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain could read the cookie, your server can be assured that the XHR came from JavaScript running on your domain. The header will not be set for cross-domain requests.

如果您想利用此功能,您必须创建操作过滤器来创建和验证 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);
}

AntiForgeryVerificationTokenCookieStore

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 });
    }
}

关于javascript - ASP.net 身份从 javascript 发送 AntiForgeryToken,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20533286/

相关文章:

javascript - 在 Vue.js 中使用 HTML Canvas 时遇到问题

asp.net - 使用 ASP.NET 进行 Paypal 订阅的代码示例

javascript - 如何让 td 颜色在第二次点击时改变颜色?

Javascript 打印代码之外的内容

javascript - 不使用 HTML5 Canvas 将图像转换为 base64

asp.net - 一个明智的 PasswordStrengthRegularExpression

asp.net-mvc - ASP.NET MVC 复杂 View

c# - MVC 将 PartialViewResult 渲染为字符串

javascript - 将 ASP.NET MVC 应用程序部署到多个虚拟目录(URL 引用和 JS 文件问题)

javascript - 如果使用 node.js 的用户 ID 在 mysql 中不存在,则抛出错误消息