2011-04-12 24 views
24

Estoy tratando de escribir una aplicación ASP.NET MVC que es una interfaz de nuestro CRM que tiene un servicio web SOAP. Me gustaría que el usuario inicie sesión en mi aplicación web usando su nombre de usuario y contraseña de CRM, y luego se autentique contra CRM, realice llamadas a servicios web en las páginas, etc.ASP.NET MVC Autenticación de formularios contra el servicio web externo

Empecé a ver cómo usar la Autenticación de formularios y cómo implementar una proveedor de membresía: puedo implementar todos los métodos necesarios para que me guste ValidateUser(), pero el problema que tengo es que después de iniciar sesión en el servicio web de CRM, se le entrega un token que se debe pasar con cada llamada de servicio web posterior, y yo soy No estoy seguro de dónde puedo almacenar esto.

Así que mis preguntas son:

  • autenticación de formularios es el camino a seguir aquí, o va a ser más fácil de manejar toda la autenticación de mí mismo y almacenar el token en la sesión.
  • Si la autenticación de formularios es el camino a seguir, dónde y cómo debo almacenar información adicional como esta. Parece que le gusta usar Autenticación de formularios, pero luego meter una carga de información adicional (que está relacionada con la autenticación) en una cookie o una sesión fuera de esto sería un desastre.

Cualquier consejo sería apreciado

Respuesta

36

Puede almacenar el token de autenticación en la parte userData de la cookie de autenticación de formularios. De esta manera estará disponible en cada solicitud.

Así, por ejemplo, una vez que verifique las credenciales de un usuario determinado se puede consultar el servicio web para obtener el token y de forma manual crear y emitir la cookie de autenticación de formularios:

[HttpPost] 
public ActionResult LogOn(string username, string password) 
{ 
    // TODO: verify username/password, obtain token, ... 
    // and if everything is OK generate the authentication cookie like this: 

    var authTicket = new FormsAuthenticationTicket(
     2, 
     username, 
     DateTime.Now, 
     DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes), 
     false, 
     "some token that will be used to access the web service and that you have fetched" 
    ); 
    var authCookie = new HttpCookie(
     FormsAuthentication.FormsCookieName, 
     FormsAuthentication.Encrypt(authTicket) 
    ) 
    { 
     HttpOnly = true 
    }; 
    Response.AppendCookie(authCookie); 

    // ... redirect 
} 

entonces se podría escribir una costumbre autorizar atributo que leerá esta información y establecer una costumbre identidad genérica:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     var isAuthenticated = base.AuthorizeCore(httpContext); 
     if (isAuthenticated) 
     { 
      string cookieName = FormsAuthentication.FormsCookieName; 
      if (!httpContext.User.Identity.IsAuthenticated || 
       httpContext.Request.Cookies == null || 
       httpContext.Request.Cookies[cookieName] == null) 
      { 
       return false; 
      } 

      var authCookie = httpContext.Request.Cookies[cookieName]; 
      var authTicket = FormsAuthentication.Decrypt(authCookie.Value); 

      // This is where you can read the userData part of the authentication 
      // cookie and fetch the token 
      string webServiceToken = authTicket.UserData; 

      IPrincipal userPrincipal = ... create some custom implementation 
              and store the web service token as property 

      // Inject the custom principal in the HttpContext 
      httpContext.User = userPrincipal; 
     } 
     return isAuthenticated; 
    } 
} 

Finalmente decorar sus controladores/acciones que requieren autenticación con este atributo:

[MyAuthorize] 
public ActionResult Foo() 
{ 
    // HttpContext.User will represent the custom principal you created 
    // and it will contain the web service token that you could use to 
    // query the remote service 
    ... 
} 
+0

Gracias, eso es brillante. Voy a intentarlo. –

+1

más el token w/s se cifra en el ticket del formulario, por lo que no puede ser robado o leído (en teoría) –

+0

Genial, pero yo pondría "base.AuthorizeCore (httpContext);" hasta el final del método, en la medida en que deseamos establecer el principal antes de la verificación de roles. – mikalai

Cuestiones relacionadas