为什么 AntiForgeryToken 验证总是失败?
Why AntiForgeryToken validation keeps failing?
我正在使用 asp.net core2
和 Angular
开发网络 API
应用 运行。详细的开发环境配置是here。
我正在尝试配置 AntiForgeryToken
验证,但它一直失败。我按照配置。 here,但我不得不修改它,因为我的 angular 应用程序和 asp.net 服务器在两个不同的端口上 运行,因为前端启动不会生成令牌。我通过在应用程序组件 ngOnInit
上调用 API
路径 (/api/Account/ContactInitialization
) 来启动后端,这使我能够生成令牌。
配置如下所示,
IServiceCollection
服务:
services.AddAntiforgery(options =>
{
options.HeaderName = "X-CSRF-TOKEN";
options.SuppressXFrameOptionsHeader = false;
});
在 IApplicationBuilder Configure
:
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]
修饰了我的方法,并在我的 header 请求中包含了 XSRF-TOKEN
cookie 内容。但是我在调用 API
之后一直收到 400 (Bad Request)
响应!我在这里错过了什么?
控制器方法,
[Authorize]
[ValidateAntiForgeryToken]
[HttpPost]
public IEnumerable<string> AutherizeCookie()
{
return new string[] { "Hello", "Auth Cookie" };
}
我的详细 [=51=] 请求如下所示,
我假设您可能遵循了 documentation,但忽略了相关部分。到目前为止,您所做的仅适用于 Angular,因为 Angular 的 $http
实际上会在 [=13= 的基础上添加 X-XSRF-TOKEN
header ] 曲奇饼。 (但是请注意,即便如此,您已经将 header 设置为 X-CSRF-TOKEN
,这在这里实际上不起作用。它需要是 X-XSRF-TOKEN
)。
但是,如果您不使用 Angular,则您有责任在 AJAX 请求中自行设置 header,而您可能忽略了这一点。在这种情况下,您实际上不需要更改任何防伪令牌配置(header 名称、设置 cookie 等)。您只需提供 header 作为 RequestVerificationToken
。例如,jQuery:
$.ajax({
...
headers:
{
"RequestVerificationToken": '@GetAntiXsrfRequestToken()'
},
...
});
这将适用于 JavaScript 的视图。如果您需要在外部 JS 中执行此操作,则需要设置 cookie,以便您可以从 cookie 中获取值。除此之外,同样的方法适用。
如果您只是想更改 header 名称,您可以这样做;您只需要将此处的 RequestVerificationHeader
部分更改为相同的值即可。
谢谢@Chris_Pratt 指出我遇到的 header 问题。但是,为了清楚起见,我还有其他问题将在下面解决。
我的 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;
});
并且 middleware
配置是,
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 即可。
不要忘记在您的请求中添加以下 header,
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.cookieService.get('ArtCoreToken')}`,
'X-XSRF-TOKEN': `${this.cookieService.get('XSRF-TOKEN')}`
});
即
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> RefreshToken()
{
await Task.Delay(1);
return StatusCode(200);
}
这对我有用。希望对你有帮助。
您需要使用 Credentials=true 发出 XHR 请求,这将使浏览器设置 cookie,否则您将收到 400 错误请求,因为 cookie 不存在并且 X-XSRF-TOKEN 未设置或已设置清空字符串
我正在使用 asp.net core2
和 Angular
开发网络 API
应用 运行。详细的开发环境配置是here。
我正在尝试配置 AntiForgeryToken
验证,但它一直失败。我按照配置。 here,但我不得不修改它,因为我的 angular 应用程序和 asp.net 服务器在两个不同的端口上 运行,因为前端启动不会生成令牌。我通过在应用程序组件 ngOnInit
上调用 API
路径 (/api/Account/ContactInitialization
) 来启动后端,这使我能够生成令牌。
配置如下所示,
IServiceCollection
服务:
services.AddAntiforgery(options =>
{
options.HeaderName = "X-CSRF-TOKEN";
options.SuppressXFrameOptionsHeader = false;
});
在 IApplicationBuilder Configure
:
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]
修饰了我的方法,并在我的 header 请求中包含了 XSRF-TOKEN
cookie 内容。但是我在调用 API
之后一直收到 400 (Bad Request)
响应!我在这里错过了什么?
控制器方法,
[Authorize]
[ValidateAntiForgeryToken]
[HttpPost]
public IEnumerable<string> AutherizeCookie()
{
return new string[] { "Hello", "Auth Cookie" };
}
我的详细 [=51=] 请求如下所示,
我假设您可能遵循了 documentation,但忽略了相关部分。到目前为止,您所做的仅适用于 Angular,因为 Angular 的 $http
实际上会在 [=13= 的基础上添加 X-XSRF-TOKEN
header ] 曲奇饼。 (但是请注意,即便如此,您已经将 header 设置为 X-CSRF-TOKEN
,这在这里实际上不起作用。它需要是 X-XSRF-TOKEN
)。
但是,如果您不使用 Angular,则您有责任在 AJAX 请求中自行设置 header,而您可能忽略了这一点。在这种情况下,您实际上不需要更改任何防伪令牌配置(header 名称、设置 cookie 等)。您只需提供 header 作为 RequestVerificationToken
。例如,jQuery:
$.ajax({
...
headers:
{
"RequestVerificationToken": '@GetAntiXsrfRequestToken()'
},
...
});
这将适用于 JavaScript 的视图。如果您需要在外部 JS 中执行此操作,则需要设置 cookie,以便您可以从 cookie 中获取值。除此之外,同样的方法适用。
如果您只是想更改 header 名称,您可以这样做;您只需要将此处的 RequestVerificationHeader
部分更改为相同的值即可。
谢谢@Chris_Pratt 指出我遇到的 header 问题。但是,为了清楚起见,我还有其他问题将在下面解决。
我的 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;
});
并且 middleware
配置是,
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 即可。 不要忘记在您的请求中添加以下 header,
const headers = new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.cookieService.get('ArtCoreToken')}`,
'X-XSRF-TOKEN': `${this.cookieService.get('XSRF-TOKEN')}`
});
即
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> RefreshToken()
{
await Task.Delay(1);
return StatusCode(200);
}
这对我有用。希望对你有帮助。
您需要使用 Credentials=true 发出 XHR 请求,这将使浏览器设置 cookie,否则您将收到 400 错误请求,因为 cookie 不存在并且 X-XSRF-TOKEN 未设置或已设置清空字符串