2010-03-02 18 views
12

Tengo una aplicación MVC que necesita iniciar sesión y verificar un usuario en contra de Active Directory. Estoy utilizando el método PrincipalContext.ValidateCredentials, pero siempre obtengo una autenticación de false.PrincipalContext.ValidateCredentials siempre devuelve FALSE

La conexión al servidor está bien. El problema parece ocurrir en el ValidateCredentials.

Aquí está mi código:

public static bool IsAuthenticated(string domain, string username, string pwd) { 
    bool IsAuthenticated = false; 

    try { 
     PrincipalContext insPrincipalContext = 
      new PrincipalContext(ContextType.Domain, domain, "DC=c1w,DC=com"); 

     username = "c1w\\" + username; 

     IsAuthenticated = insPrincipalContext.ValidateCredentials(username, pwd); 
    } 
    catch (Exception ex) 
    { 
     // Rethrow this exception 
     ExceptionPolicy.HandleException(ex, "Exception Policy"); 
    } 

    return IsAuthenticated; 
} 

Alguien sabe por qué esto estaría sucediendo?

Respuesta

7

No veo dónde inicializa la variable "pwd" Quizás debería usar ContextOption en este método para especificar exactamente el comportamiento requerido. Perdón por una respuesta demasiado amplia pero no hay muchos detalles en su pregunta

+0

Editar la pregunta para incluir todo el método. Intentaremos la sugerencia de ContextOption. Gracias. –

+5

B-Rain, La referencia de ContextOption me indicó la dirección correcta. Terminé usando ContextOptions.Negotiate en mi llamada a AD y ContextOptions.SimpleBind en las credenciales de validación. Simple Bind funcionará para mí ya que el sitio estará protegido por SSL. Gracias por su ayuda. –

+0

Subió tanto la pregunta como la respuesta porque esto también me ayudó en mi situación. En mi caso, mi máquina de desarrollo (donde el inicio de sesión funciona sin contexto especificado) está en la zona segura de la red, pero el servidor web (donde el inicio de sesión no funciona sin el contexto especificado) está en la DMZ. Usé la misma configuración que @Billy Logan: negociar en la llamada a AD y SimpleBind en la llamada de validación. – arootbeer

1

Parece que está validando el usuario con el formato de dominio \ nombredeusuario. Es posible que desee analizar el nombre de dominio de userName y el usuario ValidateCredential.

12

Así es como funciona ValidateCredentials(string, string): Primero, intenta autenticarse con las opciones de contexto Negotiate, Signing y Sealing. Si esto falla, intenta de nuevo con SimpleBind y SecureSocketLayer.

El problema es que el formato NT4 (AKA "legacy", AKA "nombre de nivel inferior") (DOMAIN\UserName, o más correctamente, NetBiosName\SamAccountName) no funciona con Negotiate. Pero funciona con SimpleBind.

Entonces, ¿qué ocurre cuando se llama al método de 2 parámetros ValidateCredentials(), es que falla al usar Negotiate porque no le gusta el formato NT4, y luego falla al usar el enlace simple.

Durante mis propias pruebas, he descubierto que la razón por la que falla incluso después de volver a utilizar el enlace simple es que no solo está utilizando SimpleBind. Está usando SimpleBind plus SecureSocketLayer. Esto significa que aún fallará si el servidor de Active Directory no está configurado correctamente para usar SSL (un escenario común para entornos de prueba).

Como se mencionó en uno de los comentarios, NUNCA, NUNCA, NUNCA desea utilizar SimpleBind por sí mismo (sin SecureSocketLayer), de lo contrario, sus contraseñas se envían a través de la red en texto sin formato.

En la naturaleza, he visto que algunos sistemas de Active Directory no permiten el uso de enlaces simples en absoluto, por lo que debe hacer que funcione con Negociar.

que he encontrado 2 maneras de hacer frente a este problema:

1) Si todo está sucediendo en el mismo dominio, debe ser capaz de llamar ValidateCredentials sólo con el nombre de usuario (nombre de cuenta SAM), dejando fuera la parte "DOMINIO \". Entonces, funcionará correctamente la primera vez con Negociar.

2) Si la parte de dominio es importante porque puede haber varios dominios implicados (es decir, Domain1\UserA y Domain2\UserA son personas diferentes), entonces se vuelve un poco más complicado. En este caso, lo que terminé haciendo fue traducir el nombre NT4 (DOMINIO \ Usuario) al formato "nombre principal del usuario" (por ejemplo, [email protected]). Hay un par de maneras diferentes de hacer esto.Lo más fácil es, probablemente, utilizar la sobrecarga de 3 parámetros de UserPrincipal.FindByIdentity(), y luego tomar el valor de la propiedad UserPrincipalName en el resultado. Otra forma sería usar un DirectorySearcher y consultar LDAP://domain para la propiedad userPrincipalName del usuario con el valor correspondiente sAMAccountName. Nota: esta solución solo funcionará si todos los dominios involucrados están en el mismo bosque.

Cuestiones relacionadas