Jak skonfigurować mój projekt mvc / webapi, aby metoda webapi wywoływana z widoku brzytwy nie zwracała strony logowania, gdy jest nieautoryzowana?
Jest to aplikacja MVC5, która ma również kontrolery WebApi do połączeń przez javascript.
Dwie metody poniżej
[Route("api/home/LatestProblems")]
[HttpGet()]
public List<vmLatestProblems> LatestProblems()
{
// Something here
}
[Route("api/home/myLatestProblems")]
[HttpGet()]
[Authorize(Roles = "Member")]
public List<vmLatestProblems> mylatestproblems()
{
// Something there
}
są wywoływane za pomocą następującego kodu kątowego:
angular.module('appWorship').controller('latest',
['$scope', '$http', function ($scope,$http) {
var urlBase = baseurl + '/api/home/LatestProblems';
$http.get(urlBase).success(function (data) {
$scope.data = data;
}).error(function (data) {
console.log(data);
});
$http.get(baseurl + '/api/home/mylatestproblems')
.success(function (data) {
$scope.data2 = data;
}).error(function (data) {
console.log(data);
});
}]
);
Więc nie jestem zalogowany, a pierwsza metoda z powodzeniem zwraca dane. druga metoda zwraca (w funkcji sukcesu) dane, które zawierają odpowiednik strony logowania. tzn. co dostaniesz w mvc, jeśli poprosisz o akcję kontrolera, która została opatrzona opcją [Autoryzuj] i nie byłeś zalogowany.
Chcę, aby zwracał 401 bez upoważnienia, dzięki czemu mogę wyświetlać różne dane dla użytkowników na podstawie tego, czy są zalogowani, czy nie. Idealnie, jeśli użytkownik jest zalogowany, chcę mieć dostęp do właściwości Użytkownik kontrolera, aby móc zwrócić dane właściwe temu członkowi.
AKTUALIZACJA: Ponieważ żadna z poniższych sugestii wydaje się już nie działać (zmiany w Tożsamości lub WebAPI), stworzyłem surowy przykład na github, który powinien zilustrować problem.
Brock Allen ma fajny post na blogu o tym, jak zwrócić 401 dla wywołań ajax przy użyciu uwierzytelniania Cookie i OWIN. http://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/
Umieść to w metodzie ConfigureAuth w pliku Startup.Auth.cs:
źródło
/api
Możesz użyć tej ścieżki do ustalenia, czy przekierować. Jest to szczególnie przydatne, jeśli masz klientów korzystających z innych formatów, takich jak JSON. Wymień wezwanie doIsAjaxRequest
zif (!context.Request.Path.StartsWithSegments(new PathString("/api")))
.private static bool IsAjaxRequest(IOwinRequest request) { return request.Query?["X-Requested-With"] == "XMLHttpRequest" || request.Headers?["X-Requested-With"] == "XMLHttpRequest"; }
Jeśli dodajesz asp.net WebApi na stronie asp.net MVC, prawdopodobnie chcesz odpowiedzieć nieautoryzowanym na niektóre żądania. Ale wtedy wkracza infrastruktura ASP.NET, a gdy spróbujesz ustawić kod statusu odpowiedzi na HttpStatusCode. Nieautoryzowane, otrzymasz 302 przekierowanie na stronę logowania.
Jeśli używasz tożsamości asp.net i uwierzytelniania opartego na owin, kod, który może pomóc rozwiązać ten problem:
źródło
Mam taką samą sytuację, w której OWIN zawsze przekierowuje odpowiedź 401 na stronę logowania z WebApi. Nasz interfejs API sieci Web obsługuje nie tylko połączenia ajax z Angular, ale także połączenia mobilne, Win Form. Dlatego rozwiązanie sprawdzające, czy żądanie jest żądaniem ajax, nie jest tak naprawdę posortowane w naszym przypadku.
Zdecydowałem, że innym podejściem jest wstrzyknięcie nowej odpowiedzi nagłówka:
Suppress-Redirect
jeśli odpowiedzi pochodzą z webApi. Implementacja dotyczy modułu obsługi:I zarejestruj ten moduł obsługi na poziomie globalnym WebApi:
Tak więc podczas uruchamiania OWIN możesz sprawdzić, czy nagłówek odpowiedzi ma
Suppress-Redirect
:źródło
W poprzednich wersjach ASP.NET musiałeś robić całą masę rzeczy aby to zadziałało.
Dobrą wiadomością jest to, że używasz ASP.NET 4.5. możesz wyłączyć przekierowanie uwierzytelniania formularzy za pomocą nowego HttpResponse.SuppressFormsAuthenticationRedirect właściwości .
W
Global.asax
:EDYCJA : Możesz także rzucić okiem na ten artykuł rzucić Siergieja Zwezdina, który ma bardziej wyrafinowany sposób na osiągnięcie tego, co próbujesz zrobić.
Odpowiednie fragmenty kodu i narracja autora wklejone poniżej. Oryginalny autor kodu i narracji - Sergey Zwezdin .
Po pierwsze - ustalmy, czy bieżące żądanie HTTP jest żądaniem AJAX. Jeśli tak, powinniśmy wyłączyć zastępowanie HTTP 401 HTTP 302:
Po drugie - dodajmy warunek :: jeśli użytkownik zostanie uwierzytelniony, wtedy wyślemy HTTP 403; i HTTP 401 w przeciwnym razie.
Dobra robota. Teraz powinniśmy zastąpić wszystkie zastosowania standardowego AuthorizeAttribute tym nowym filtrem. Może nie mieć zastosowania do sime facetów, którzy są estetami kodu. Ale nie znam innego sposobu. Jeśli masz, przejdźmy do komentarzy.
Ostatni, co powinniśmy zrobić - dodać obsługę HTTP 401/403 po stronie klienta. Możemy użyć ajaxError w jQuery, aby uniknąć duplikacji kodu:
Wynik -
źródło
Jeśli uruchamiasz swój projekt
Web API
w swoimMVC
projekcie, musisz utworzyć niestandardowy,AuthorizeAttribute
aby zastosować go do swoichAPI
metod. W ramachIsAuthorized
override
musisz złapać prąd,HttpContext
aby zapobiec przekierowaniu, tak jak to:źródło
Używając integracji z Azure Active Directory, podejście wykorzystujące
CookieAuthentication
oprogramowanie pośrednie nie działało dla mnie. Musiałem wykonać następujące czynności:Jeśli żądanie pochodzi z samej przeglądarki (a nie na przykład wywołania AJAX), nagłówek Accept będzie zawierać ciąg
html
. Tylko wtedy, gdy klient zaakceptuje HTML, uważam przekierowanie za przydatne.Moja aplikacja kliencka może obsłużyć 401, informując użytkownika, że aplikacja nie ma już dostępu i musi się ponownie załadować, aby zalogować się ponownie.
źródło
Miałem także aplikację MVC5 (System.Web) z WebApi (używając OWIN) i chciałem tylko zapobiec zmianie 401 odpowiedzi z WebApi na 302 odpowiedzi.
Dla mnie zadziałało stworzenie niestandardowej wersji WebApi AuthorizeAttribute w następujący sposób:
I używać go zamiast standardowego atrybutu autoryzacji WebApi. Użyłem standardowego MVC AuthorizeAttribute, aby zachować zachowanie MVC bez zmian.
źródło
SuppressFormsAuthenticationRedirect
flagi spowodowało, że po prostu zwrócił mi istniejącą 401.Wystarczy zainstalować następujący pakiet NeGet
Zainstaluj pakiet Microsoft.AspNet.WebApi.Owin
Napisz następujący kod w pliku WebApiConfig.
źródło
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
przeciwnym razieUser.Identity.IsAuthenticated
jest zawszefalse
jeśli chcesz złapać Content-Type == application / json, możesz użyć tego kodu:
pozdrowienia!!
źródło
Trudno mi było uzyskać zarówno kod stanu, jak i odpowiedź tekstową, pracując w metodach OnAuthorization / HandleUnauthorizedRequest. To okazało się dla mnie najlepszym rozwiązaniem:
źródło
Po wielu staraniach, aby uniknąć przekierowań na stronę logowania, zdałem sobie sprawę, że jest to w rzeczywistości całkiem odpowiednie dla atrybutu Autoryzuj. To znaczy idź i uzyskaj autoryzację. Zamiast połączeń api, które nie są autoryzowane, chciałem po prostu nie ujawniać żadnych informacji hakerom. Ten cel łatwiej było osiągnąć bezpośrednio, dodając nowy atrybut wyprowadzony z funkcji Autoryzuj, który zamiast tego ukrywa zawartość jako błąd 404:
źródło
Mieszanie MVC i WebAPI, jeśli żądanie jest nieautoryzowane, przekieruje do strony logowania nawet w żądaniu WebAPI. W tym celu możemy dodać poniższy kod, aby wysłać odpowiedź na aplikację mobilną
źródło
Dzięki chłopaki!
W moim przypadku połączyłem odpowiedzi cuongle i Shivy i otrzymałem coś takiego:
W module obsługi OnException () dla wyjątków API:
W kodzie konfiguracji uruchamiania aplikacji:
źródło
W MVC 5 z Dot Net Framework 4.5.2 otrzymujemy „application / json, plaint text ..” pod nagłówkiem „Accept” Przyjemnie będzie użyć następującego:
źródło