Nat*_*lus 6 cookies csrf angularjs asp.net-core
我有一个使用angularJS的.net核心应用程序,我想保护受基于cookie的身份验证保护的api调用.我按照本文中的步骤操作:
https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");我的服务配置XSRF-TOKEN在加载页面时在开发人员工具中看到了cookie.我看到X-XSRF-TOKEN标题被添加到我的$ http发送请求中.
我已将[AutoValidateAntiforgeryToken]我的控制器添加到处理ajax请求的控制器中.
我可以按预期通过此api端点使GET请求正常.但是,我收到400错误,没有任何有关PUT和POST请求错误的详细信息.
我知道这X-XSRF-TOKEN是请求,(在chrome dev工具的网络选项卡中看到)所以我不确定我缺少什么来允许正确接收这些请求.
TL; DR:为什么.net核心拒绝我的有效AntiforgeryToken?
更新尝试@ joey建议的解决方案,但它没有工作,仍然收到400个响应.下面的代码反映了我试图解决这个问题的另一个解决方案(aka angularjs的解决方案,为跨站点脚本保护设置默认cookie和标头)
我还尝试配置AngularJS来改变cookie和标题名称与我在我的配置中匹配的名称Startup.cs.我更改了他们的名字以尝试XSRF-TOKEN(cookie)和X-XSRF-TOKEN(标题)以及,CSRF-TOKEN并且X-CSRF-TOKEN,虽然angular中的配置正确使用我提供的新默认值,但.net核心中的身份验证代码仍然无效.
有关更多信息,请参阅我如何配置AngularJS:
app.config(function ($httpProvider) {
$httpProvider.defaults.xsrfHeaderName = 'X-CSRF-TOKEN';
$httpProvider.defaults.xsrfCookieName = 'CSRF-TOKEN';
});
Run Code Online (Sandbox Code Playgroud)
这是ConfigureServices我Startup.cs文件中的行:
services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");
Run Code Online (Sandbox Code Playgroud)
最后这里是我添加到文件Configure方法的Startup.cs代码:
app.Use(next => context =>
{
string path = context.Request.Path.Value;
if (path.Contains("/MyProtectedPath/"))
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken,
new CookieOptions { HttpOnly = false });
}
return next(context);
});
Run Code Online (Sandbox Code Playgroud)
更新2: 我已将以下内容添加到控制器操作中:
if (HttpContext.Request.Method.ToLower(CultureInfo.InvariantCulture) != "get")
{
await _antiforgery.ValidateRequestAsync(HttpContext);
}
Run Code Online (Sandbox Code Playgroud)
AntiforgeryValidationException: The provided antiforgery token was meant for a different claims-based user than the current user.
我想也许antiforgery.GetAndStoreTokens(context)可能会覆盖页面加载时发送的当前cookie,所以我只在GET请求上点击该代码,但我得到了相同的帖子结果.
更新3 感谢@joey的帮助,我查看了我的startup.cs文件,并在单独的分支中使用了UseAuthentication:
app.Use(next => context => //note: order of these use statements is key. keep this antiforgery section above auth!
{
string path = context.Request.Path.Value;
if (path.ToLower(CultureInfo.InvariantCulture).Contains("/campaigns/proxy/"))
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions { HttpOnly = false });
}
return next(context);
});
// Use Basic Auth for /api
app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), branch =>
{
branch.UseBasicAuth();
});
// Use Identity for everything except /api
app.UseWhen(context => !context.Request.Path.StartsWithSegments(new PathString("/api")), branch =>
{
app.UseAuthentication(); // required for .net core 2.0 authentication
});
Run Code Online (Sandbox Code Playgroud)
我不确定为什么我的令牌在这一点上会被视为无效......
在您发布的代码中,您要添加 header X-XSRF-TOKEN,但 header 应该是X-CSRF-TOKEN.
您链接的网页中的示例提供了示例:
services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");
Run Code Online (Sandbox Code Playgroud)
更新:
感谢您通过附加代码和信息进行澄清。这里选择的实现 CSRF 的方法是将令牌作为初始 HTML 文件响应的标头进行传递。以下是如何为 SPA Web 应用程序配置此类情况的示例:
app.Use(next => context =>
{
string path = context.Request.Path.Value;
if (
string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase)
)
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
}
return next(context);
});
Run Code Online (Sandbox Code Playgroud)
但是,如果您的服务配置为使用 String.Contains 方法 [1],antiforgery.GetAndStoreTokens(context)则会为包含任何位置的任何路径调用/MyProtectedPath/。这意味着它的配置方式不仅匹配/MyProtectedPath/,还/MyProtectectedPath/a/b/c匹配 或/a/b/c/MyProtectedPath/。
要检查适用 HTTP 方法的后续请求中发送的 CSRF 令牌,如下所示:
if (string.Equals("POST", context.Request.Method, StringComparison.OrdinalIgnoreCase))
{
await antiforgery.ValidateRequestAsync(context);
// The line above will throw if the CSRF token is invalid.
}
Run Code Online (Sandbox Code Playgroud)
如果在此之前针对任何匹配路径调用该方法GetAndStoreTokens,则令牌将在检查之前被覆盖,这就是为什么 .net 示例通常GetAndStoreTokens首先排序,但具有查看路径和 HTTP 方法的特定条件。
[1] https://msdn.microsoft.com/en-us/library/dy85x1sa(v=vs.110).aspx
| 归档时间: |
|
| 查看次数: |
1291 次 |
| 最近记录: |