Я использую ASP. NET Core 2.2 с AspNetCore.Authentication .
Я пытаюсь использовать Post
вызов в моем cshtml
Форма компонента представления _Layout:
<form asp-controller="Home" asp-action="SearchResults" method="post" enctype="multipart/form-data" asp-antiforgery="true" novalidate>
(...)
</form>
Мое намерение состоит в том, чтобы замаскировать URL-адрес с помощью свойств поиска, чтобы усложнить сканирование и удаление в Интернете. Мой метод Post
обновляет поля stati c моего контроллера и перенаправляет на мой метод Index Get
, где отображаются результаты поиска:
private static SearchViewModel _searchModel;
private static string _sortOrder;
private static int? _pageNumber;
(...)
[HttpPost]
[AllowAnonymous]
public IActionResult SearchResults(SearchViewModel searchModel, string sortOrder, int? pageNumber = 1)
{
_searchModel = searchModel;
_sortOrder = sortOrder;
_pageNumber = pageNumber;
return RedirectToAction(nameof(Index));
}
И Get
подпись метода:
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Index()
{
//refering to updated fields
}
Идея, вдохновленная этим SO-ответом .
И настройка идентичности / аутентификации Setup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<AppUser, IdentityRole>(opts => {
opts.User.RequireUniqueEmail = true;
opts.User.AllowedUserNameCharacters = null; //disable validation
opts.Password.RequiredLength = 8;
opts.Password.RequireNonAlphanumeric = false;
opts.Password.RequireLowercase = false;
opts.Password.RequireUppercase = false;
opts.Password.RequireDigit = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddAntiforgery(x => x.HeaderName = "X-CSRF-TOKEN");
.Services.ConfigureApplicationCookie(options =>
{
//previous cookies not valid
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromDays(1);
});
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
options.Filters.Add<AuditUserActionFilter>();
});
(...)
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAntiforgery antiforgery)
{
(...)
app.Use(next => context =>
{
if (context.Request.Path == "/")
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });
}
return next(context);
});
app.UseAuthentication();
}
}
Я верю, что это ключ: На самом деле, когда я отправляю форму Post
в качестве гостя (не аутентифицирована), все работает нормально. Но после входа в систему при отправке формы я получаю исключение:
Предоставлен токен защиты от подделки, предназначенный для другого пользователя на основе утверждений
Также см. Ниже мою аутентификацию пользователя процесс:
if (user != null)
{
await _signInManager.SignOutAsync();
var result = await _signInManager.PasswordSignInAsync(user, details.Password, false, false);
if (result.Succeeded)
{
if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
return Redirect(returnUrl);
else
return RedirectToAction(nameof(Account));
}
else if (result.IsLockedOut || result.IsNotAllowed)
{
ViewBag.Message = "You are not allowed to sign in.";
return View("Error");
}
else
{
ModelState.AddModelError(nameof(UserLoginViewModel.Password), "Incorrect password.");
return View("Index");
}
}
Я пробовал несколько подходов: здесь и здесь безрезультатно. Но они для более старых версий ASP. NET Core. Я не уверен, как я должен обновить свои токены защиты от подделки для аутентифицированного пользователя?
Возможные причины моей проблемы: 1) неправильное понимание Post -> Get form call. 2) не понимает, как куки-файлы аутентификации работают в ASP. NET Core аутентификации. 3) неправильное понимание процесса аутентификации в целом.
PS Когда я удаляю
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
из:
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
options.Filters.Add<AuditUserActionFilter>();
});
Я могу сделать Post
звонок. Но я верю, что это не удивительно.
РЕДАКТИРОВАТЬ: По какой-то причине, когда я отправляю форму из другого представления (форма находится в компоненте представления _Layout), чем Home / Index ( там, где я отображаю результаты поиска), исключений для защиты от подделки нет.
Это потому, что действие HomeController
Index
равно Get
? После добавления атрибута Post / Get
:
[AllowAnonymous]
[HttpGet, HttpPost]
public async Task<IActionResult> Index()
у меня такое же исключение, как и раньше. После добавления:
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Index()
Я вообще не могу загрузить представление, потому что оно запрашивает токен.
Как его обойти?