C# 为什么AntiForgeryToken验证一直失败?
我正在开发一个webC# 为什么AntiForgeryToken验证一直失败?,c#,asp.net-core-2.0,csrf-protection,antiforgerytoken,C#,Asp.net Core 2.0,Csrf Protection,Antiforgerytoken,我正在开发一个webAPI应用程序,使用asp.net core2和Angular运行。详细的开发环境配置如下所示。 我正在尝试配置AntiForgeryToken验证,但一直失败。我遵循了配置,但是我不得不修改它,因为我的angular应用程序和asp.net服务器在两个不同的端口上运行,因为前端启动程序没有生成令牌。我通过调用app组件ngOnInit上的API路径(/API/Account/ContactInitialization)启动后端,该路径允许我生成令牌。 配置如下所示 ISer
API
应用程序,使用asp.net core2
和Angular
运行。详细的开发环境配置如下所示。
我正在尝试配置AntiForgeryToken
验证,但一直失败。我遵循了配置,但是我不得不修改它,因为我的angular应用程序和asp.net服务器在两个不同的端口上运行,因为前端启动程序没有生成令牌。我通过调用app组件ngOnInit
上的API
路径(/API/Account/ContactInitialization
)启动后端,该路径允许我生成令牌。
配置如下所示
IServiceCollection
服务:
services.AddAntiforgery(options =>
{
options.HeaderName = "X-CSRF-TOKEN";
options.SuppressXFrameOptionsHeader = false;
});
在IApplicationBuilder配置中:
app.Use(next => context =>
{
string path = context.Request.Path.Value;
if (
string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(path, "/api/Account/ContactInitialization", StringComparison.OrdinalIgnoreCase) ||
string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
{
// We can send the request token as a JavaScript-readable cookie,
// and Angular will use it by default.
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
}
return next(context);
});
asp.net。生成两组密钥
我用[ValidateAntiForgeryToken]
修饰了我的方法,并在我的头请求中包含XSRF-TOKEN
cookie内容。然而,在调用API
之后,我一直收到400(错误请求)
响应!我错过了什么
控制器方法
[Authorize]
[ValidateAntiForgeryToken]
[HttpPost]
public IEnumerable<string> AutherizeCookie()
{
return new string[] { "Hello", "Auth Cookie" };
}
[授权]
[ValidateAntiForgeryToken]
[HttpPost]
公共IEnumerable AutherizeCookie()
{
返回新字符串[]{“Hello”,“Auth Cookie”};
}
我的详细标题请求如下所示
我想你可能遵循了,但掩盖了相关的部分。到目前为止,您所做的工作仅适用于Angular,因为Angular的$http
实际上会基于XSRF-TOKEN
cookie添加X-XSRF-TOKEN
头。(但是,请注意,即使如此,您还是将标题设置为X-CSRF-TOKEN
,这在这里实际不起作用。它必须是X-XSRF-TOKEN
)
但是,如果您没有使用Angular,那么您需要自己在AJAX请求中设置头,这可能是您忽略的。在这种情况下,您实际上不需要更改任何antiforgery令牌配置(头名称、设置cookie等)。您只需提供标题作为RequestVerificationToken
。例如,使用jQuery:
$.ajax({
...
headers:
{
"RequestVerificationToken": '@GetAntiXsrfRequestToken()'
},
...
});
这将适用于视图中的JavaScript。如果需要在外部JS中执行此操作,则需要设置cookie,以便可以从cookie中获取值。除此之外,同样的方法也适用
如果您只是想更改标题名称,您可以这样做;您只需将此处的RequestVerificationHeader
部分更改为相同的值。谢谢,@Chris\u Pratt指出我遇到的标题问题。然而,为了明确起见,我还有其他问题将在下面讨论
我的CORS
配置错误,我的工作代码如下:
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.WithOrigins("https://www.artngcore.com:4200") //Note: The URL must be specified without a trailing slash (/).
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
options.SuppressXFrameOptionsHeader = false;
});
而中间件
配置是
app.Use(next => context =>
{
string path = context.Request.Path.Value;
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false,
Secure = true // set false if not using SSL });
return next(context);
});
在控制器中
[Route("/api/[controller]/[action]")]
[EnableCors("CorsPolicy")]
public class AccountController : ArtCoreSecuredController ....
这里的诀窍是,令牌必须在身份验证后刷新。仅在身份验证(登录)后调用API即可。
别忘了在请求中添加以下标题
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.cookieService.get('ArtCoreToken')}`,
'X-XSRF-TOKEN': `${this.cookieService.get('XSRF-TOKEN')}`
});
i、 e
[HttpGet]
[异名]
公共异步任务刷新令牌()
{
等待任务。延迟(1);
返回状态码(200);
}
这就是我的工作。希望能有所帮助。您需要使用credentials=true发出XHR请求,这将使浏览器设置cookie,否则您将收到400个错误请求,因为cookie不存在,并且X-XSRF-TOKEN未设置或设置为空字符串。我使用Angular,它默认情况下会像您所说的那样附加cookie。我将提供的令牌头更改为X-XSRF-Token
,但仍然得到相同的响应,代码如下所示services.AddAntiforgery(options=>{options.HeaderName=“X-XSRF-Token”;})代码>和<代码>var令牌=antiforgery.GetAndStoreTokens(上下文);context.Response.Cookies.Append(“X-XSRF-TOKEN”,tokens.RequestToken,…
我没有把这篇文章写得太长,但是我已经发布了我的启动配置,在我的代码中,我把我的标题改为X-XSRF-TOKEN
cookie名称应该是XSRF-TOKEN
改为var tokens=antiforgery.GetAndStoreTokens(context);context.Response.Cookies.Append(“XSRF-TOKEN”,tokens.RequestToken
,我将标题保留为X-XSRF-TOKEN
,不起作用,我希望我收到错误,只有400个错误的request.LGTM。尝试从中间件中删除if
条件?如果你的意思是,我在生成令牌方面没有问题,否则请解释为什么我没有删除该条件了解为什么应该进行RefreshToken调用?是因为CORS吗?对我来说,情况基本相同,只是我没有启用CORS,我需要注销并再次登录我的webapp才能进行调用。请参考此问题,根据设计,密钥必须在验证后刷新。嗯,我对此没有什么疑问。不使用ValidateAntiForegeryToken
表示您的控制器实际上没有验证csrf令牌,而只是检查CORS策略?编辑:实际上刚刚测试了这一点;我从前端删除了实际的csrf令牌(请求发送的是后端未提供的伪csrf令牌),并且它允许请求
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> RefreshToken()
{
await Task.Delay(1);
return StatusCode(200);
}