2008-12-18 11 views
11

J'ai une application d'authentification centrale sur le serveur a. Le serveur b a une ou plusieurs applications sur le même domaine qui doivent s'authentifier auprès du serveur a. Il est assez facile de le configurer pour que les applications serveur b redirigent vers le serveur a. Ce qui n'est pas si simple, c'est que le ReturnURL soit absolu.Authentification par formulaire + ASP.NET MVC absolu ReturnURL

Voici la ride. L'application consommatrice sur le serveur b a deux contrôleurs, un public et un sécurisé. Si la décoration [authorize] est placée sur une action dans le public (qui est le contrôleur par défaut), j'obtiens l'URL absolue correcte. Cependant, si c'est dans son propre contrôleur, j'obtiens une URL relative.

Je peux intercepter l'événement sur pré-demande dans les applications consommatrices, mais j'ai besoin que certaines parties du site soient publiques, et non l'ensemble.

Des idées?

Répondre

15

La méthode standard AuthorizeAttribute fonctionne en définissant le code d'état de réponse sur 401 si la demande n'est pas authentifiée. Cela déclenche la réponse standard du module d'authentification par défaut à une demande non autorisée. Je suppose que vous utilisez l'authentification basée sur des formulaires, qui créerait l'URL de retour en fonction de l'URL de la requête. Dans ce cas, probablement une URL relative. Une chose que vous pouvez faire est de ne pas vous fier au comportement intégré, vous pouvez implémenter un SSOAuthorizeAttribute qui étend la classe AuthorizeAttribute et remplace OnAuthorization. Vous pouvez ensuite extraire le loginUrl de l'élément forms dans la configuration Web et créer votre propre RedirectResult et extraire l'URL return de la propriété HttpContext.Request.Url.AbsoluteUri dans le paramètre 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

Merci pour la réponse utile, pour toute personne utilisant ce, notez que 'filterContext.Cancel' n'est pas là dans MVC4, maintenant, vous avez juste besoin de régler le résultat. – Menahem

+0

@Menahem - J'ai supprimé la ligne inutile. Merci pour l'avertissement. – tvanfosson

5

En supposant l'authentification des formulaires, dans le répertoire apps serveur B web.config, définissez l'attribut loginUrl sur l'étiquette des formulaires à une méthode d'action du contrôleur qui broquettes sur l'URL absolue avant de rediriger vers le serveur A.

Config sur le serveur B

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

La méthode d'action ressemblerait

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

comme https://stackoverflow.com/a/583608/80589 mais plus court:

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