Asp.net web api 防伪令牌+;Web API(-MVC)

Asp.net web api 防伪令牌+;Web API(-MVC),asp.net-web-api,antiforgerytoken,Asp.net Web Api,Antiforgerytoken,在没有ASP.NET MVC的情况下,如何在ASP.NET Web API中使用防伪令牌 Stephen Walther的这篇文章是“使用ASP.NET MVC防止跨站点请求伪造攻击”。。。但他的解决方案包括MVC/Razor,在我的前端,我不打算包括它。还有很多类似的文章,解决方案是添加@Html.AntiForgeryToken(),但这不是我的解决方案 后来,我解决了另一个问题,“同一原产地政策”:,这是否也是防止CSRF的解决方案?我不这么认为。我的问题是我不想使用MVC,只想提供由We

在没有ASP.NET MVC的情况下,如何在ASP.NET Web API中使用防伪令牌

Stephen Walther的这篇文章是“使用ASP.NET MVC防止跨站点请求伪造攻击”。。。但他的解决方案包括MVC/Razor,在我的前端,我不打算包括它。还有很多类似的文章,解决方案是添加
@Html.AntiForgeryToken()
,但这不是我的解决方案


后来,我解决了另一个问题,“同一原产地政策”:,这是否也是防止CSRF的解决方案?我不这么认为。

我的问题是我不想使用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值添加到标题中:

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();
    }
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();
            }
        }
    }
最后,在
HttpModule
中,在处理对api的任何调用之前,检查cookie是否与标头匹配:

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();
    }
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";
    }
}
这就是我最后要做的