Почему проверка AntiForgeryToken не проходит?
Я занимаюсь веб API
приложение работает с использованием asp.net core2
а также Angular
, Подробная конфигурация среды разработки находится здесь. Я пытаюсь настроить AntiForgeryToken
проверка, но она продолжает терпеть неудачу. Я следил за конфигом. здесь, но мне пришлось изменить его, так как мое угловое приложение и серверы asp.net работают на двух разных портах, потому что запуск внешнего интерфейса не генерирует токен. Я запускаю бэкэнд, вызывая API
дорожка (/api/Account/ContactInitialization
) в компоненте приложения ngOnInit
что позволило мне сгенерировать токен. Конфиг показан ниже,
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]
и я включил XSRF-TOKEN
содержание куки в моем запросе заголовка. пока я продолжаю получать 400 (Bad Request)
ответ после вызова API
! что мне здесь не хватает?
Метод Контроллера,
[Authorize]
[ValidateAntiForgeryToken]
[HttpPost]
public IEnumerable<string> AutherizeCookie()
{
return new string[] { "Hello", "Auth Cookie" };
}
мой подробный запрос заголовка выглядит ниже,
3 ответа
Я предполагаю, что вы, вероятно, следовали документации, но затушевали соответствующие биты. То, что вы сделали, работает только для Angular, потому что Angular $http
на самом деле добавит X-XSRF-TOKEN
заголовок на основе XSRF-TOKEN
печенье. (Обратите внимание, однако, что даже тогда вы установили свой заголовок как X-CSRF-TOKEN
, который на самом деле не будет работать здесь. Это должно быть X-XSRF-TOKEN
).
Однако, если вы не используете Angular, вы сами отвечаете за настройку заголовка в ваших AJAX-запросах, что вы, вероятно, игнорируете. В этом случае вам на самом деле не нужно изменять какую-либо конфигурацию токена защиты от подделки (имена заголовков, настройки файлов cookie и т. Д.). Вам просто нужно предоставить заголовок как RequestVerificationToken
, Например, с помощью jQuery:
$.ajax({
...
headers:
{
"RequestVerificationToken": '@GetAntiXsrfRequestToken()'
},
...
});
Это будет работать для JavaScript в поле зрения. Если вам нужно сделать это во внешнем JS, вам нужно будет установить cookie, чтобы вместо этого вы могли получить значение из cookie. Помимо этого, применяется та же методология.
Если вы просто хотите изменить имя заголовка, вы можете сделать это; вам просто нужно изменить RequestVerificationHeader
часть здесь к тому же значению.
Вам необходимо выполнить запрос XHR withCredentials=true, который заставит браузер установить cookie, в противном случае вы получите неверный запрос 400, потому что cookie отсутствует, а X-XSRF-TOKEN либо не установлен, либо установлен в пустую строку
Спасибо, @Chris_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;
});
и 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 сразу после аутентификации (логина) сделает это. не забудьте добавить следующий заголовок к вашему запросу,
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);
}
это то, что сработало для меня. Надеюсь, поможет.