24

Tengo un sitio ASP.NET que debe usar la Autenticación de formularios y no la Autenticación de Windows para acceder a ActiveDirectoryMembershipProvider. El sitio debe usar formularios porque necesitan un formulario de entrada diseñado en lugar de la ventana emergente de autenticación del navegador que usa la autenticación de Windows.Suplantar usando Autenticación de formularios

El sitio debe suplantar al usuario que inició sesión a través de Active Directory para acceder a los archivos específicos del usuario.

Sin embargo, el WindowsIdentity.GetCurrent() no es el mismo que el HttpContext.Current.User.Identity aunque mi web.config contiene:

<authentication mode="Forms"> 
    <forms loginUrl="login.aspx" timeout="480"/> 
</authentication> 
<identity impersonate="true" /> 

no puedo usar LoginUser() y la WindowsIdentity.Impersonate() porque necesito hacerse pasar como el usuario de AD para obtener sus permisos específicos y no sé la contraseña del usuario, ya que las formas se encarga de inicio de sesión.

¿es posible tal vez de los login.aspx.cs, para tomar el System.Web.UI.WebControls.Login.Password, a continuación, guardar el token LoginUser() en una variable de sesión para WindowsIdentity.Impersonate() después? ¿O tal vez un método mucho más seguro de suplantar el camino correcto?

estoy confundido por qué las formas de autenticación puede no de forma automática <identity impersonate="true" />

He leído este http://msdn.microsoft.com/en-us/library/ms998351.aspx pero utiliza la autenticación de Windows.

+0

Aquí está la solución utilicé: me dio acceso a los archivos IUSER_, entonces puedo comprobar obtener los permisos de cada archivo o carpeta a través DirectorySecurity.GetAccessRules(). Si 'FileSystemAccessRule.Value ==" DOMAIN \\ "+ Page.User.Identity.Name' en las reglas de acceso, entonces agrego ese archivo o carpeta a una lista. Por último, mostrar la lista de archivos. Así que, en lugar de suplantar, otorgo al IUSR_ acceso total y verifico los permisos manualmente en las cosas que necesito que el usuario tenga acceso. – Robert

Respuesta

19

hacerse pasar por un usuario mediante la autenticación de formularios se puede hacer. El siguiente código funciona.

El Visual Studio Magazine article al que se refiere Robert es un recurso excelente. Hay algunos problemas con el código de ejemplo en el artículo, por lo que he incluido algunos códigos de trabajo a continuación.

Nota: Si está utilizando Visual Studio, asegúrese de iniciarlo como "Ejecutar como administrador" para evitar problemas con la suplantación de bloqueo de UAC.

// in your login page (hook up to OnAuthenticate event) 
protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e) 
{ 
    int token; 
    // replace "YOURDOMAIN" with your actual domain name 
    e.Authenticated = LogonUser(LoginUser.UserName,"YOURDOMAIN",LoginUser.Password,8,0,out token); 
    if (e.Authenticated) { 
     Session.Add("principal", new WindowsPrincipal(new WindowsIdentity(new IntPtr(token)))); 
    } 
} 

[DllImport("advapi32.dll", SetLastError = true)] 
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, 
    int dwLogonType, int dwLogonProvider, out int TokenHandle); 


// in global.asax.cs 
void Application_PreRequestHandlerExecute(object send, EventArgs e) 
{ 
    if (Thread.CurrentPrincipal.Identity.IsAuthenticated == true && HttpContext.Current.Session != null) { 
     WindowsPrincipal windowsPrincipal = (WindowsPrincipal)Session["principal"]; 
     Session["principal"] = (GenericPrincipal)Thread.CurrentPrincipal; 
     Thread.CurrentPrincipal = windowsPrincipal; 
     HttpContext.Current.User = windowsPrincipal; 
     HttpContext.Current.Items["identity"] = ((WindowsIdentity)windowsPrincipal.Identity).Impersonate(); 
    } 
} 

// in global.asax.cs 
void Application_PostRequestHandlerExecute(object send, EventArgs e) 
{ 
    if (HttpContext.Current.Session != null && Session["principal"] as GenericPrincipal != null) { 
     GenericPrincipal genericPrincipal = (GenericPrincipal)Session["principal"]; 
     Session["principal"] = (WindowsPrincipal)Thread.CurrentPrincipal; 
     Thread.CurrentPrincipal = genericPrincipal; 
     HttpContext.Current.User = genericPrincipal; 
     ((WindowsImpersonationContext)HttpContext.Current.Items["identity"]).Undo(); 
    } 
} 

// test that impersonation is working (add this and an Asp:Label to a test page) 
protected void Page_Load(object sender, EventArgs e) 
{ 
    try { 
     // replace YOURSERVER and YOURDB with your actual server and database names 
     string connstring = "data source=YOURSERVER;initial catalog=YOURDB;integrated security=True"; 
     using (SqlConnection conn = new SqlConnection(connstring)) { 
      conn.Open(); 
      SqlCommand cmd = new SqlCommand("SELECT SUSER_NAME()", conn); 
      using (SqlDataReader rdr = cmd.ExecuteReader()) { 
       rdr.Read(); 
       Label1.Text = "SUSER_NAME() = " + rdr.GetString(0); 
      } 
     } 
    } 
    catch { 
    } 
} 

Actualización:

También debe manejar Application_EndRequest, porque las llamadas como Response.End() pasará por alto Application_PostRequestHandlerExecute.

Otro problema es que WindowsIdentity puede obtener basura recolectada, por lo que debe crear una nueva WindowsIdentity y WindowsPrincipal desde el token de inicio de sesión en cada solicitud.

Update2:

no estoy seguro de por qué esto se está downvoted, porque funciona. He agregado la firma de Pinvoke y algunos códigos de prueba. Nuevamente, inicie Visual Studio usando "Ejecutar como administrador". Busca cómo hacerlo si no sabes cómo.

+0

FWIW, (soy la pregunta OP) Elevo esta respuesta y la cambié a la respuesta correcta. – Robert

+0

Este enfoque no funcionó para MVC en mis pruebas, pero lo logré reemplazando BeginExecute y EndExecute desde System.Web.Mvc.Controller. El problema de este enfoque es que necesito poner esto en un BaseController y cambiar todos los controladores existentes para que hereden de este BaseController. – Luty

+0

También estoy usando MVC. Tuve que comentar la sesión ["principal"] = (GenericPrincipal) Thread.CurrentPrincipal; línea porque no podría convertir un web.PrincipalRole en un GenericPrincipal. Sin embargo, en realidad no importaba porque solo necesitaba suplantar a un usuario cuando me conectaba a la base de datos, así que no necesitaba almacenar el usuario suplantado para usarlo en todo el sitio. Lo que significa que tampoco puse nada en global.asax.cs. Solo lo incluí en mi clase de db. – Kevin

0

Si sus usuarios utilizan IE, puede activar la seguridad integrada para el sitio web y sus usuarios serán autenticados de forma silenciosa (sin cuadro de diálogo de inicio de sesión ni página de inicio de sesión). Tu suplantación funcionará. Si necesita orientar otros navegadores, es posible que esto no funcione (probablemente se le presentará al usuario un cuadro de diálogo de inicio de sesión).

Su suplantación actual nunca funcionará porque sus usuarios inician sesión con una cuenta que no sea la de su dominio. No puede esperar que el sitio suplante a un usuario que no haya proporcionado sus credenciales. Eso iría en contra de los principios básicos de seguridad.

+2

Es una extranet, por lo que los usuarios acceden a archivos internos utilizando cuentas AD desde fuera de la LAN. Al usar un ActiveDirectoryMembershipProvider, los usuarios inician sesión con su cuenta de dominio. El almacén de usuarios real es AD, puede iniciar sesión utilizando la autenticación Forms o Windows con éxito, pero no puede acceder a los archivos cuando usa Formularios, solo cuando usa Windows porque Forms usa la cuenta IUSR_ *. – Robert

0

Hemos tenido el mismo problema recientemente, el cliente quería que sus usuarios puedan iniciar sesión por cuenta de AD y luego esta credencial debe usarse para acceder a Analysis Service y a todas las demás bases de datos . Lo querían de esa manera porque implementaron un sistema de auditoría y todos los accesos se deben hacer con la cuenta iniciada actual.

Intentamos la autenticación de formularios y Win32 LogonUser() API para suplantar la parte, funcionó pero también nos pide la contraseña del usuario como texto sin formato. Más tarde, decidimos utilizar la autenticación de Windows, nos ahorra mucho tiempo (no más autenticación AD, suplantación manual). Por supuesto, tampoco había una página de inicio de sesión elegante.

-6

En Visual Studio instalar NuGet Abra su solución

Luego, en la consola de ejecución de paquete Instalar Paquete 51Degrees.mobi

A continuación, añadir 51Degrees a su sitio web. A continuación, puede editar 51Degrees.mobi.config en los datos de su aplicación para eliminar la sección de redirección.

Ahora va a tener hasta la fecha capacidades del navegador

-1

Por si acaso, y un poco tarde, me encontré con algo que funciona para mí y es muy simple pero, por supuesto, es sólo para propósitos de prueba ...

acaba de establecer una cookie con su nombre de usuario.

//Login button. You can give whatever input to the form 
protected void Login_Click(object sender, EventArgs e) 
{ 
    FormsAuthentication.SetAuthCookie("your_username", createPersistentCookie: true); 
    Response.Redirect("~/"); 
} 

Cualquier comentario aceptados ...

+0

Esta pregunta es sobre cómo hacer que 'WindowsIdentity.Impersonate()' funcione. No veo cómo esta respuesta intenta responder esa pregunta – KyleMit

Cuestiones relacionadas