Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/470.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 启用CORS的REST API浏览器客户端的CSRF保护_Javascript_C#_Asp.net Web Api_Cors_Csrf - Fatal编程技术网

Javascript 启用CORS的REST API浏览器客户端的CSRF保护

Javascript 启用CORS的REST API浏览器客户端的CSRF保护,javascript,c#,asp.net-web-api,cors,csrf,Javascript,C#,Asp.net Web Api,Cors,Csrf,API.sample.com背后有一个API,app.sample.com背后有一个基于浏览器的webapp(单页,Javascript驱动),以及其他非基于浏览器的客户端 API支持基本身份验证和基于令牌的身份验证,并将令牌打包到浏览器的cookie中 要使设置适用于浏览器,必须启用CORS并设置凭据: var cors = new EnableCorsAttribute("https://app.sample.com", "*", "GET,POST,PUT,DELETE"); cors.S

API.sample.com
背后有一个API,
app.sample.com
背后有一个基于浏览器的webapp(单页,Javascript驱动),以及其他非基于浏览器的客户端

API支持基本身份验证和基于令牌的身份验证,并将令牌打包到浏览器的cookie中

要使设置适用于浏览器,必须启用CORS并设置凭据:

var cors = new EnableCorsAttribute("https://app.sample.com", "*", "GET,POST,PUT,DELETE");
cors.SupportsCredentials = true;
cors.PreflightMaxAge = 3600;
config.EnableCors(cors);
现在我研究了CSRF漏洞,发现AJAX被源设置阻止,
看不到任何响应数据,但
-提交内容可被利用

为了保护表单,我在混合中添加了一个防伪令牌,并为没有设置
AllowAnonymousAttribute
的控制器操作的每个请求验证它

我想使用
System.Web.Helpers.AntiForgery
类,但它需要设置主体标识,而在登录时验证凭据时则不是这样-仅在后续请求时

因此,我想到了浏览器客户端在验证凭据之后立即请求CSRF令牌,在每个请求中将令牌作为头发送,服务器在FilterAttribute中验证令牌。例如

[HttpGet, Route("xsrf"), AllowAnonymous]
public IHttpActionResult GetCSRFToken()
{
    // AllowAnonymous is set to allow requests without csrf token to reach this action
    if (User.Identity.IsAuthenticated)
    {
        string cookieToken, formToken;
        AntiForgery.GetTokens(null, out cookieToken, out formToken);
        // or set a cookie
        return Ok(cookieToken + ":" + formToken);
    }
    return Unauthorized();
}

public类ValidateXSRFTokenAttribute:AuthorizationFilterAttribute
{
授权时的公共覆盖无效(HttpActionContext actionContext)
{
//仅当操作上未设置cookie身份验证和AllowAnonymousAttribute时应用
如果(actionContext.RequestContext.Principal.Identity.AuthenticationType==DefaultAuthenticationTypes.ApplicationOkie&&
!actionContext.ActionDescriptor.GetCustomAttributes().Any())
{
尝试
{
字符串cookieToken=“”;
字符串formToken=“”;
IEnumerable标记头;
if(actionContext.Request.Headers.TryGetValues(“X-XSRF-Token”,out-tokenHeaders))
{
var tokens=tokenHeaders.First().Split(“:”);
if(tokens.Length==2)
{
cookieToken=tokens[0]。Trim();
formToken=tokens[1].Trim();
}
}
防伪。验证(cookieToken,formToken);
}
抓住
{
actionContext.Response=新的HttpResponseMessage(HttpStatusCode.Unauthorized)
{
ReasonPhrase=“反XSRF验证失败。”
};
}
}
基于授权(actionContext);
}
}
这个实现正确吗?有什么需要改进的吗? 仍然可以让服务器使用
提交发送CSRF令牌,因此保护取决于无法根据同源策略在javascript中读取该响应

或者最好在登录时直接设置我自己的CSRF令牌

public class ValidateXSRFTokenAttribute : AuthorizationFilterAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        // apply only if cookie-authentication and no AllowAnonymousAttribute set on the action
        if (actionContext.RequestContext.Principal.Identity.AuthenticationType == DefaultAuthenticationTypes.ApplicationCookie &&
            !actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any())
        {
            try
            {
                string cookieToken = "";
                string formToken = "";
                IEnumerable<string> tokenHeaders;
                if (actionContext.Request.Headers.TryGetValues("X-XSRF-Token", out tokenHeaders))
                {
                    var tokens = tokenHeaders.First().Split(':');
                    if (tokens.Length == 2)
                    {
                        cookieToken = tokens[0].Trim();
                        formToken = tokens[1].Trim();
                    }
                }
                AntiForgery.Validate(cookieToken, formToken);
            }
            catch
            {
                actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
                {
                    ReasonPhrase = "Anti-XSRF Validation Failed."
                };
            }
        }

        base.OnAuthorization(actionContext);
    }
}