2008-12-18 34 views
11

Tengo una aplicación de autenticación central en el servidor a. El servidor b tiene una o más aplicaciones en el mismo dominio que necesitan autenticarse desde el servidor a. Es bastante fácil de configurar para que las aplicaciones del servidor b se redirijan al servidor a. Lo que no es tan fácil es conseguir que ReturnURL sea absoluto.Autenticación de formularios + ASP.NET MVC absolute ReturnURL

Aquí está la arruga. La aplicación de consumo en el servidor b tiene dos controladores, uno público y otro seguro. Si la decoración [autorizar] se coloca en una acción en el público (que es el controlador predeterminado), obtengo la URL absoluta adecuada. Sin embargo, si está en su propio controlador, obtengo una URL relativa.

Puedo interceptar el evento de solicitud previa en las aplicaciones consumidoras, pero necesito que algunas partes del sitio sean públicas, no todo el éxito.

Ideas?

Respuesta

15

La forma en que funciona el estándar AuthorizeAttribute es estableciendo el código de estado de respuesta en 401 si la solicitud no está autenticada. Esto inicia la respuesta estándar del módulo de autenticación predeterminado a una solicitud no autorizada. Supongo que está utilizando la autenticación basada en formularios, que construiría la url de retorno en función de la url de la solicitud. En este caso, probablemente una URL relativa.

Una cosa que podría hacer es confiar en el comportamiento incorporado, puede implementar un SSOAuthorizeAttribute que amplíe la clase AuthorizeAttribute y anule OnAuthorization. A continuación, puede extraer el loginUrl del elemento forms en la configuración web y crear su propio RedirectResult y extraer el returnUrl de la propiedad HttpContext.Request.Url.AbsoluteUri en el parámetro 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

gracias por la respuesta útil para cualquier persona que utiliza este, tenga en cuenta que 'filterContext.Cancel' no está allí en MVC4, ahora sólo tiene que fijar el resultado. – Menahem

+0

@Menahem: he eliminado la línea innecesaria. Gracias por la advertencia. – tvanfosson

5

Suponiendo que la autenticación de formularios, en el web.config aplicaciones servidor B, establece el atributo loginUrl en la etiqueta formas a un método Acción controlador que tachuelas en la URL absoluta antes de redirigir al servidor A.

Config en el servidor B

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

El método de acción se vería

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

como https://stackoverflow.com/a/583608/80589 pero más corto:

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