Я пытаюсь заставить ASP.NET Core Identity возвращать 401, когда пользователь не вошел в систему. Я добавил атрибут [Authorize]
в свой метод, и вместо того, чтобы возвращать 401, он возвращает 302. Я пробовал массу предложений но ничего не работает, включая services.Configure
и app.UseCookieAuthentication
установку LoginPath
на null
или PathString.Empty
.
Как вернуть 401 вместо 302 в ASP.NET Core?
Ответы (8)
Начиная с ASP.NET Core 2.x:
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
Если заголовок запроса содержит 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);
}
Для ядра 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;
};
});
return Task.CompletedTask;
вместо return Task.FromResult<object>(null);
- person SerjG; 11.04.2018
services.AddIdentity(…)
или AddDefaultIdentity(…)
- person Jamie F; 12.09.2018
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);
}
};
});
Источник:
Хорошо, после того, как покопался в aspNetCore.Identity.Test/IdentityOptionsTest.cs " основные модульные тесты Я наконец нашел рабочее решение. Вы должны добавить следующее к своему вызову в services.AddIdentity
services.AddIdentity<ApplicationUser, IdentityRole>(o => {
o.Cookies.ApplicationCookie.AutomaticChallenge = false;
});
WWW-Authenticate
заголовок ДОЛЖЕН быть предоставлен на 401. If the protected resource request does not include authentication credentials or does not contain an access token that enables access to the protected resource, the resource server MUST include the HTTP "WWW-Authenticate" response header field
- person urbanhusky; 17.05.2017
Для ASP.NET Core 3.x (предварительная версия) с использованием аутентификации Identity with 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
. Это «грустно», но факт. Этот ТАК-ответ наконец-то пролил свет во тьме.
Я уже больше суток чешу затылок и перепробовала много разных вариантов:
- Переопределить атрибут авторизации (больше не нужно переопределять в 3.x)
- Указание options.Cookie.EventType с помощью Cookie (ошибка времени выполнения)
- options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme (было сказано, что носитель JWT не будет перенаправлять на страницу входа)
- И, конечно же, настройка
ApplicationCookie
(но перед вызовомAddIdentity
, который не работает.
Все это не сработало. Но с ответом выше я наконец получил возвращенное сообщение 401 Unauthorized (которое, кстати, должно быть Unauthenticated).
Для меня в 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;
};
}
);
В продолжение, я объединил предыдущие ответы в следующие:
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);
}
}