2008-12-18 15 views
11

Mam centralną aplikację uwierzytelniającą na serwerze a. Serwer b ma jedną lub więcej aplikacji w tej samej domenie, które muszą uwierzytelnić się z serwera a. Jest to dość łatwe do skonfigurowania, aby serwer b apps przekierowywał się do serwera a. Co nie jest takie proste, to uzyskanie zwrotu z inwestycji jest absolutne.Forms authentication + ASP.NET MVC absolute ReturnURL

Oto zmarszczka. Konsumowanie aplikacji na serwerze b ma dwa kontrolery, jeden publiczny i jeden zabezpieczony. Jeśli dekoracja [autoryzuj] zostanie umieszczona w akcji publicznej (która jest domyślnym kontrolerem), otrzymam prawidłowy bezwzględny adres URL. Jednak jeśli jest to jego własny kontroler, otrzymuję względny adres URL.

Mogę przechwycić zdarzenie typu "pre-request" w aplikacjach zużywających, ale potrzebuję niektórych części witryny, aby były dostępne publicznie, a nie całego roztrzaskania.

Pomysły?

Odpowiedz

15

Sposób działania standardowego AuthorizeAttribute polega na ustawieniu kodu statusu odpowiedzi na 401, jeśli żądanie nie jest uwierzytelnione. Spowoduje to wyszukanie standardowej odpowiedzi domyślnego modułu uwierzytelniającego na nieautoryzowane żądanie. Zakładam, że korzystasz z uwierzytelniania opartego na formularzach, które tworzy URL powrotny na podstawie adresu URL w żądaniu. W tym przypadku prawdopodobnie jest to względny adres URL.

Jedną z rzeczy, które można zrobić, zamiast polegać na wbudowanym zachowaniu, można zaimplementować SSOAuthorizeAttribute, która rozszerza klasę AuthorizeAttribute i zastępuje OnAuthorization. Następnie można wyodrębnić loginUrl z elementu formularzy w konfiguracji sieci i zbudować własny obiekt RedirectResult i pobrać wartość returnUrl z właściwości HttpContext.Request.Url.AbsoluteUri w parametrze AuthorizationContext.

public class SSOAuthorizeAttribute : AuthorizeAttribute 
{ 
     public override void OnAuthorization( 
          AuthorizationContext filterContext) 
     { 
      if (filterContext == null) 
      { 
       throw new ArgumentNullException("filterContext"); 
      } 

      if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
      { 
       // get from cached variable from web configuration 
       string loginUrl = ... 
       if (filterContext.HttpContext.Request != null) 
       { 
        loginUrl += "?ReturnUrl=" + filterContext.HttpContext 
                  .Request 
                  .Url 
                  .AbsoluteUri; 
       } 

       filterContext.Result = new RedirectResult(loginUrl); 
      } 
     } 
} 
+0

dzięki za pomocne odpowiedzi, dla każdego, kto używa tego należy pamiętać, że 'filterContext.Cancel' nie istnieje w MVC4, teraz po prostu trzeba ustawić wynik. – Menahem

+0

@Menahem - Usunąłem niepotrzebną linię. Dzięki za ostrzeżenie. – tvanfosson

5

Zakładając uwierzytelniania formy w web.config aplikacje Serwer B ustawić atrybut loginUrl na etykiecie formy sposobu działania regulatora, które napadach na bezwzględny adres URL przed przekierowanie do serwera A

konfiguracji na serwerze B

<authentication mode="Forms"> 
    <forms loginUrl="/Account/LoginRedirect" /> 
</authentication> 

Sposób działania będzie wyglądać

public RedirectResult LoginRedirect(string returnUrl) 
    { 
     var requestUrl = HttpContext.Current.Request.Url; 
     return LoginUrlOnServerA + 
       "?returnUrl=" +   
       HttpUtility.UrlEncode(string.Format("http://{0}:{1}{2}", 
       requestUrl.Host, 
       requestUrl.Port, 
       HttpUtility.UrlDecode(returnUrl))); 
    } 
0

jako https://stackoverflow.com/a/583608/80589 ale krócej:

public RedirectResult LogOn(string returnUrl) 
{ 
    var r = new Uri(Request.Url, returnUrl).ToString(); 
    return Redirect("https://logonserver.com/?return_url=" + Url.Encode(r)); 
} 
Powiązane problemy