2016-08-06 10 views
9

Próbuję uzyskać tożsamość rdzenia ASP.NET, aby zwrócić 401, gdy użytkownik nie jest zalogowany. Dodałem atrybut [Authorize] do mojej metody i zamiast zwracać 401 zwraca 302. Próbowałem tonę sugestii, ale nic nie działa, w tym services.Configure i app.UseCookieAuthentication ustawienie LoginPath do lub PathString.Empty.Jak zwrócić 401 zamiast 302 w ASP.NET Core?

Odpowiedz

11

Od ASP.NET podstawowej 2.x:

services.ConfigureApplicationCookie(options => 
{ 
    options.Events.OnRedirectToLogin = context => 
    { 
     context.Response.StatusCode = 401;  
     return Task.CompletedTask; 
    }; 
}); 
+0

również, twoje wezwanie do usług. AddIdentity musi przyjść przed tym –

5

Dobra, po kopaniu w asp.net core unit tests W końcu znalazłem działające rozwiązanie. Trzeba dodać następujące wezwanie do services.AddIdentity

services.AddIdentity<ApplicationUser, IdentityRole>(o => { 
    o.Cookies.ApplicationCookie.AutomaticChallenge = false; 
}); 
+0

Czy to nadal przekierowuje użytkownika na stronę logowania? Dostaję ALOT z ruchu na strony, które po kliknięciu przekierują do strony logowania z powodu 302. Nadal chcę, żeby to działało, ale chcę, żeby wszystkie boty zawiodły to połączenie, więc nigdy go nie nazywają znowu (401/403). 302 nadal będzie im powtarzał, aby nadal do niego dzwonili. (To jest dla tych, którzy nie honorują pliku robots.txt, gdzie konkretnie "nie zezwalam na ten wzorzec adresu URL") – ganders

+1

@ganders No. Jeśli chcesz, aby twoja aplikacja zachowywała się w określony sposób na 401, będziesz sam sobie z tym poradzić. Zazwyczaj numer 401 powinien zawierać nagłówek WWW-Authenticate, który opisuje sposób uwierzytelniania. –

+0

Nagłówek 'WWW-Authenticate' MUSI być podany na 401. ' Jeśli żądanie chronionego zasobu nie zawiera poświadczeń uwierzytelniających lub nie zawiera znacznika dostępu, który umożliwia dostęp do chronionego zasobu, serwer zasobów MUSI zawierać HTTP "WWW -Authenticate "pole nagłówka odpowiedzi" – urbanhusky

5
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); 
     } 
    }; 
}); 

Źródło:

https://www.illucit.com/blog/2016/04/asp-net-5-identity-302-redirect-vs-401-unauthorized-for-api-ajax-requests/

+0

To jest dokładnie to, czego potrzebowałem. Dzięki! –

+1

Niestety, to nie działa na rdzeń tożsamości 2 –

1

Dla Asp.net Core 2 stosowany zamiast

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.FromResult<object>(null); 
     } 
     context.Response.Redirect(context.RedirectUri); 
     return Task.FromResult<object>(null); 
    }; 
}); 
+0

To rozwiązanie działa doskonale w Core 2! Dziękuję Ci –

0

Jeśli nagłówek wniosek zawiera X-Zamówiony-with: XMLHttpRequest kod statusu będzie 401 zamiast 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); 
    } 

Zobacz na GitHub: https://github.com/aspnet/Security/blob/5de25bb11cfb2bf60d05ea2be36e80d86b38d18b/src/Microsoft.AspNetCore.Authentication.Cookies/Events/CookieAuthenticationEvents.cs#L40-L52