Tworzę witrynę internetową dla wielu dzierżawców, na której znajdują się strony dla klientów. Pierwszy segment adresu URL będzie ciągiem identyfikującym klienta, zdefiniowanym w Global.asax przy użyciu następującego schematu routingu adresu URL:
"{client}/{controller}/{action}/{id}"
Działa to dobrze w przypadku adresów URL, takich jak / foo / Home / Index.
Jednak gdy używam atrybutu [Authorize], chcę przekierować do strony logowania, która również używa tego samego schematu mapowania. Więc jeśli klient to foo, strona logowania będzie miała postać / foo / Account / Login zamiast stałego / Account / Login przekierowania zdefiniowanego w web.config.
MVC używa HttpUnauthorizedResult, aby zwrócić nieautoryzowany stan 401, który, jak przypuszczam, powoduje przekierowanie ASP.NET do strony zdefiniowanej w web.config.
Czy ktoś wie, jak zastąpić zachowanie przekierowania logowania ASP.NET? A może lepiej byłoby przekierować w MVC, tworząc niestandardowy atrybut autoryzacji?
EDYCJA - Odpowiedź: po zagłębieniu się w źródło .Net zdecydowałem, że niestandardowy atrybut uwierzytelniania jest najlepszym rozwiązaniem:
public class ClientAuthorizeAttribute: AuthorizeAttribute
{
public override void OnAuthorization( AuthorizationContext filterContext )
{
base.OnAuthorization( filterContext );
if (filterContext.Cancel && filterContext.Result is HttpUnauthorizedResult )
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "client", filterContext.RouteData.Values[ "client" ] },
{ "controller", "Account" },
{ "action", "Login" },
{ "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
});
}
}
}
Odpowiedzi:
Myślę, że głównym problemem jest to, że jeśli zamierzasz korzystać z wbudowanej klasy ASP.NET FormsAuthentication (i nie ma powodu, aby tego nie robić), coś pod koniec dnia zadzwoni,
FormsAuthentication.RedirectToLoginPage()
co będzie aby spojrzeć na jeden skonfigurowany adres URL. Zawsze jest tylko jeden adres URL logowania i właśnie tak go zaprojektowali.Mój problem (prawdopodobnie implementacja Rube Goldberga) polegałby na przekierowaniu do jednej strony logowania w katalogu głównym, udostępnianej wszystkim klientom, powiedzmy / account / login. Ta strona logowania w rzeczywistości niczego nie wyświetla; sprawdza parametr ReturnUrl lub jakąś wartość, którą mam w sesji lub plik cookie, który identyfikuje klienta i używa go do natychmiastowego przekierowania 302 do określonej strony / klient / konto / login. Jest to dodatkowe przekierowanie, ale prawdopodobnie niezauważalne i pozwala korzystać z wbudowanych mechanizmów przekierowania.
Inną opcją jest utworzenie własnego atrybutu niestandardowego zgodnie z opisem i unikanie wszystkiego, co wywołuje
RedirectToLoginPage()
metodę wFormsAuthentication
klasie, ponieważ zastąpisz go własną logiką przekierowania. (Możesz stworzyć swoją własną klasę, która jest podobna.) Ponieważ jest to klasa statyczna, nie znam żadnego mechanizmu, za pomocą którego mógłbyś po prostu wstrzyknąć swój własny alternatywny interfejs i sprawić, by magicznie działał z istniejącym atrybutem [Authorize], który ciosy, ale ludzie robili już wcześniej podobne rzeczy .Mam nadzieję, że to pomoże!
źródło
Application_AuthenticateRequest
(zobacz moją odpowiedź poniżej).W wersji RTM programu ASP.NET MVC brakuje właściwości Cancel. Ten kod działa z ASP.NET MVC RTM:
Edycja: Możesz chcieć wyłączyć domyślny loginUrl uwierzytelniania formularzy w web.config - na wypadek, gdyby ktoś zapomniał, że masz niestandardowy atrybut i przez pomyłkę użyje wbudowanego atrybutu [Authorize].
Zmodyfikuj wartość w web.config:
Następnie utwórz metodę akcji „ERROR”, która rejestruje błąd i przekierowuje użytkownika do najbardziej ogólnej strony logowania, jaką masz.
źródło
Moim rozwiązaniem tego problemu była niestandardowa
ActionResult
klasa:źródło
Mimo to, jeśli zdecydujesz się użyć wbudowanego ASP.NET FormsAuthentication, możesz pominąć
Application_AuthenticateRequest
wGlobal.asax.cs
następujący sposób:źródło