【问题标题】:Anti-Forgery Token + Web API (- MVC)防伪令牌 + Web API (- MVC)
【发布时间】:2014-10-03 03:27:59
【问题描述】:

如何在没有 ASP.NET MVC 的情况下通过 ASP.NET Web API 使用 Anti-Forgery Token?

Stephen Walther 在http://stephenwalther.com/archive/2013/03/05/security-issues-with-single-page-apps 中有这篇文章“使用 ASP.NET MVC 防止跨站点请求伪造攻击”...但他的解决方案包括 MVC/Razor,我不打算在我的前端包括它。并且有很多类似的文章,解决方法是添加@Html.AntiForgeryToken(),但这不是我的解决方案。

后来,我解决了另一个问题,“同源策略”:http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api,这也是防止 CSRF 的解决方案吗?我不这么认为。

【问题讨论】:

标签: asp.net-web-api antiforgerytoken


【解决方案1】:

我的问题是我不想使用 MVC,而只想提供由 WebApi 支持的静态 html 文件。这是我所做的(这可行吗?)创建一个 Http 模块,在提供任何静态文件时设置随机 cookie 值。例如:

public class XSRFModule : IHttpModule {
    ...

    void context_EndRequest(object sender, EventArgs e) {
        if (Path.GetExtension(HttpContext.Current.Request.Path) == ".html") {
            HttpContext.Current.Response.Cookies.Add(new HttpCookie("XSRF-TOKEN", Guid.NewGuid().ToString()));
        }
    }
}

然后在你的html页面中,在调用你的api时使用javascript将cookie值添加到header中:

function callApi() {
        xhr = new XMLHttpRequest();
        xhr.open("GET", "api/data", true);
        var regex = /\b(?:XSRF-TOKEN=)(.*?)(?=\s|$)/
        var match = regex.exec(document.cookie);
        xhr.setRequestHeader("X-XSRF-TOKEN", match[1]);
        xhr.send();
    }

最后,在您的HttpModule 中,在处理对您的 api 的任何调用之前检查 cookie 是否与标头匹配:

void context_BeginRequest(object sender, EventArgs e)
    {
        if (HttpContext.Current.Request.Path.StartsWith("/api"))
        {
            string fromCookie = HttpContext.Current.Request.Cookies.Get("XSRF-TOKEN").Value;
            string fromHeader = HttpContext.Current.Request.Headers["X-XSRF-TOKEN"];
            if (fromCookie != fromHeader)
            {
                HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.Forbidden;
                HttpContext.Current.Response.End();
            }
        }
    }

您需要将HttpOnly 标志设置为FALSE,以便您域中的javascript 可以读取cookie 并设置标头。我不是安全专家,所以我想从社区的其他一些成员那里得到一些关于这个解决方案的反馈。

编辑

如果您使用的是 OWIN,则可以使用全局操作过滤器和中间件插件:

Startup.cs

app.UseStaticFiles(new StaticFileOptions {
            OnPrepareResponse = (responseContext) => {
                responseContext.OwinContext.Response.Cookies.Append("XSRF-TOKEN", Guid.NewGuid().ToString());
            },
            FileSystem = "wwwroot"
        });

XsrfFilter.cs

public class XsrfFilter : ActionFilterAttribute {
    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) {

        string fromCookie = actionContext.Request.Headers.GetCookies("XSRF-TOKEN").FirstOrDefault()["XSRF-TOKEN"].Value;
        string fromHeader = actionContext.Request.Headers.GetValues("X-XSRF-TOKEN").FirstOrDefault();

        if (fromCookie == fromHeader) return;

        actionContext.Response = new HttpResponseMessage(HttpStatusCode.OK);
        actionContext.Response.ReasonPhrase = "bad request";
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-11
    • 2017-12-29
    • 1970-01-01
    • 2014-04-26
    • 2014-01-23
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多