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