Я пытаюсь вернуть Core Identity ASP.NET 401, когда пользователь не войдет в систему. Я добавил атрибут [Authorize]
к моему методу и вместо того, чтобы возвращать 401, он возвращает 302. Я попробовал массу предложений, но ничего не работает, в том числе services.Configure
и app.UseCookieAuthentication
установка LoginPath
в null
или PathString.Empty
.
Как вернуть 401 вместо 302 в ASP.NET Core?
Ответ 1
Как ASP.NET Core 2.x:
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
Ответ 2
Если заголовок запроса содержит X-Requested-With: XMLHttpRequest, код состояния будет 401 вместо 302
private static bool IsAjaxRequest(HttpRequest request)
{
return string.Equals(request.Query["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal) ||
string.Equals(request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal);
}
Ответ 3
Для ядра asp.net MVC ИСПОЛЬЗУЙТЕ ЭТО ВМЕСТО
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logout");
options.Events.OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/api")
&& context.Response.StatusCode == StatusCodes.Status200OK)
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
});
Ответ 4
services.Configure<IdentityOptions>(options =>
{
options.Cookies.ApplicationCookie.LoginPath = new PathString("/");
options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents()
{
OnRedirectToLogin = context =>
{
if (context.Request.Path.Value.StartsWith("/api"))
{
context.Response.Clear();
context.Response.StatusCode = 401;
return Task.FromResult(0);
}
context.Response.Redirect(context.RedirectUri);
return Task.FromResult(0);
}
};
});
Источник:
Ответ 5
Хорошо, после того, как я прокопал в тесты ядра ядра asp.net, я наконец нашел рабочее решение. Вы должны добавить к вызову services.AddIdentity
services.AddIdentity<ApplicationUser, IdentityRole>(o => {
o.Cookies.ApplicationCookie.AutomaticChallenge = false;
});
Ответ 6
У меня на ASP.NET Core 2.2.0 работало только это:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(
options =>
{
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logout");
options.Events.OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/api")
&& context.Response.StatusCode == StatusCodes.Status200OK)
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
}
);
Ответ 7
Для ASP.NET Core 3.x (предварительный просмотр), использующего идентификацию с проверкой подлинности с помощью cookie, вот что сделал:
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<IdentityContext>()
.AddDefaultTokenProviders()
.AddRoles<IdentityRole>();
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
Это то, что мы видим повсюду в разных вариациях. НО, суть в том, что ConfigureApplicationCookie
должно быть указано ПОСЛЕ AddIdentity
. Это "грустно" но верно. Этот SO ответ наконец-то принес свет в темноту.
Я целый день ломал голову и пробовал разные варианты:
- Переопределить атрибут Authorize (больше не нужно переопределять в 3.x)
- Указание options.Cookie.EventType с файлом cookie (ошибка времени выполнения)
- options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme (Было сказано, что однонаправленный канал JWT не будет перенаправлять на страницу входа)
- И, конечно, настройка
ApplicationCookie
(но до вызоваAddIdentity
, который не работает.
Это все не сработало. Но с ответом выше я наконец-то вернул 401 UnAuthorized (кстати, это должно быть UnAuthenticated)
Ответ 8
В продолжение я объединил предыдущие ответы в следующие:
1. Startup.cs
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = new PathString("/Account/Login");
options.LogoutPath = new PathString("/Account/Logout");
options.Events.OnRedirectToAccessDenied = context =>
{
if (wlt_AjaxHelpers.IsAjaxRequest(context.Request))
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
});
2. Вспомогательный пользовательский класс
public static class wlt_AjaxHelpers
{
public static bool IsAjaxRequest( HttpRequest request )
{
return string.Equals(request.Query["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal) ||
string.Equals(request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal);
}
}