我正在用Angular实现一个网站.js,这是一个ASP.NET WebAPI后端.

有棱角的js有一些内置的功能来帮助防止csrf.在每个http请求上,它都会查找名为"XSRF-TOKEN"的cookie,并将其作为名为"X-XSRF-TOKEN"的头文件提交.

这依赖于Web服务器能够在对用户进行身份验证后设置XSRF-TOKEN cookie,然后判断X-XSRF-TOKEN头以获取传入请求.

Angular documentation个州:

要利用这一点,您的服务器需要在第一个HTTP GET请求时在名为XSRF-TOKEN的JavaScript可读会话cookie中设置一个令牌.对于后续的非GET请求,服务器可以验证cookie是否与X-XSRF-Token HTTP报头匹配,因此确保只有在您的域上运行的JavaScript可以读取该令牌.该令牌对于每个用户都必须是唯一的,并且必须可由服务器验证(以防止JavaScript组成自己的令牌).我们建议令牌是您站点的身份验证Cookie的摘要,并使用SALT以增加安全性.

我找不到任何关于ASP的好例子.NET WebAPI,所以我在各种来源的帮助下推出了自己的.我的问题是——有人能看出代码有什么问题吗?

首先,我定义了一个简单的助手类:

public class CsrfTokenHelper
{
    const string ConstantSalt = "<ARandomString>";

    public string GenerateCsrfTokenFromAuthToken(string authToken)
    {
        return GenerateCookieFriendlyHash(authToken);
    }

    public bool DoesCsrfTokenMatchAuthToken(string csrfToken, string authToken) 
    {
        return csrfToken == GenerateCookieFriendlyHash(authToken);
    }

    private static string GenerateCookieFriendlyHash(string authToken)
    {
        using (var sha = SHA256.Create())
        {
            var computedHash = sha.ComputeHash(Encoding.Unicode.GetBytes(authToken + ConstantSalt));
            var cookieFriendlyHash = HttpServerUtility.UrlTokenEncode(computedHash);
            return cookieFriendlyHash;
        }
    }
}

然后我在授权控制器中有以下方法,我在调用FormsAuthentication后调用它.SetAuthCookie():

    // http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-(csrf)-attacks
    // http://docs.angularjs.org/api/ng.$http
    private void SetCsrfCookie()
    {
        var authCookie = HttpContext.Current.Response.Cookies.Get(".ASPXAUTH");
        Debug.Assert(authCookie != null, "authCookie != null");
        var csrfToken = new CsrfTokenHelper().GenerateCsrfTokenFromAuthToken(authCookie.Value);
        var csrfCookie = new HttpCookie("XSRF-TOKEN", csrfToken) {HttpOnly = false};
        HttpContext.Current.Response.Cookies.Add(csrfCookie);
    }

然后我有一个自定义属性,可以添加到控制器中,让它们判断csrf头:

public class CheckCsrfHeaderAttribute : AuthorizeAttribute
{
    //  http://stackoverflow.com/questions/11725988/problems-implementing-validatingantiforgerytoken-attribute-for-web-api-with-mvc
    protected override bool IsAuthorized(HttpActionContext context)
    {
        // get auth token from cookie
        var authCookie = HttpContext.Current.Request.Cookies[".ASPXAUTH"];
        if (authCookie == null) return false;
        var authToken = authCookie.Value;

        // get csrf token from header
        var csrfToken = context.Request.Headers.GetValues("X-XSRF-TOKEN").FirstOrDefault();
        if (String.IsNullOrEmpty(csrfToken)) return false;

        // Verify that csrf token was generated from auth token
        // Since the csrf token should have gone out as a cookie, only our site should have been able to get it (via javascript) and return it in a header. 
        // This proves that our site made the request.
        return new CsrfTokenHelper().DoesCsrfTokenMatchAuthToken(csrfToken, authToken);
    }
}

最后,当用户注销时,我清除Csrf令牌:

HttpContext.Current.Response.Cookies.Remove("XSRF-TOKEN");

有人能发现这种方法存在任何明显(或不太明显)的问题吗?

推荐答案

没有任何问题指出的代码,所以我认为问题回答.

Asp.net相关问答推荐

页面刷新后如何存储JS Select 数据

从组件属性调用异步方法的正确方法

此版本的 SQL Server 不支持用户实例登录标志.连接将关闭

如何使多行的 TextBox 控件无法调整大小?

Server.Transfer 在执行子请求时抛出错误.如何解决?

'Access-Control-Allow-Origin' 标头包含多个值 '*, *',但只允许一个

asp.net dropdownlist - 在 db 值之前添加空行

如何从 web.config 中读取系统值并在 ASP.NET MVC C# 方法中使用

ASP.NET Web 应用程序消息框

如何在 ASP.NET 中仅在调试模式下执行代码

您如何以编程方式填写表格并发布网页?

Asp.net 中的下拉列表验证使用必填字段验证器

错误:无法在 Web 服务器上开始调试... ASP.NET 4.0

如何将图像 url 转换为 system.drawing.image

在 ASP.NET MVC 中使用 Razor 创建可重用的 HTML 视图组件

如何在 ASP.Net 的客户端 (JavaScript) 上判断 Page.Validate()?

实体框架:如何解决外键约束可能导致循环或多个级联路径?

主机与 DnsSafeHost

您可以从 web.config 文件中的其他位置提取 log4net AdoNetAppender 的 connectionString 吗?

ASP.NET 邮箱验证器正则表达式