2010-07-19 3 views
0

Nous développons une application Web qui utilise l'authentification par formulaires et ActiveDirectoryMembershipProvider pour authentifier les utilisateurs par rapport à Active Directory. Nous avons rapidement découvert que le fournisseur ne permettait pas de spécifier un mot de passe vide/vide, même si cela est parfaitement légal dans Active Directory (à condition qu'une politique de mot de passe préventive ne soit pas en place).Comment faire pour que ActiveDirectoryMembershipProvider accepte un mot de passe vide?

Avec l'aimable autorisation du réflecteur:

private void CheckPassword(string password, int maxSize, string paramName) 
{ 
    if (password == null) 
    { 
     throw new ArgumentNullException(paramName); 
    } 
    if (password.Trim().Length < 1) 
    { 
     throw new ArgumentException(SR.GetString("Parameter_can_not_be_empty", new object[] { paramName }), paramName); 
    } 
    if ((maxSize > 0) && (password.Length > maxSize)) 
    { 
     throw new ArgumentException(SR.GetString("Parameter_too_long", new object[] { paramName, maxSize.ToString(CultureInfo.InvariantCulture) }), paramName); 
    } 
} 

À moins d'écrire notre propre fournisseur personnalisé, est-il possible de passer outre cette fonctionnalité en utilisant la magie de .NET?

Répondre

1

Je ne vous pouvez pas beleive modifier ce comportement sans créer une classe dérivée et overiding chaque méthode qui appelle la méthode CheckPassword privée. Je ne recommanderais pas cette option cependant, je recommanderais que vous examiniez votre conception et vous demandiez s'il est approprié d'autoriser des mots de passe vierges dans votre application. Bien qu'ils soient valides dans AD, il est inhabituel que cela soit autorisé dans la pratique et il a un impact sur d'autres choses dans un réseau Windows, par ex. Je pense que les paramètres par défaut pour les partages de fichiers réseau interdisent à tout utilisateur avec un mot de passe vide de se connecter au partage.

+0

Vous pouvez vous connecter aux partages de fichiers et mapper des lecteurs réseau, etc. avec un mot de passe vide/vide, il est pris en charge sur l'ensemble du forum, à l'exception de ActiveDirectoryMembershipProvider. Vous avez raison, il n'y a aucun moyen de contourner ce comportement spécifiquement sans créer une sous-classe. – fletcher

0

Vous pourriez peut-être envisager d'utiliser l'usurpation d'identité, mais je ne sais pas si vous aurez le même problème. Si c'est pour autoriser un utilisateur, vous pouvez utiliser l'emprunt d'identité pour essayer de "usurper l'identité" de l'utilisateur sur la machine. Je ne sais pas si ça aide, mais je faisais quelque chose de similaire à ça l'autre semaine. Ont mis le code ci-dessous si tout cela aide .. :)

using System; 
using System.Runtime.InteropServices; 

public partial class Test_Index : System.Web.UI.Page { 
protected void Page_Load(object sender, EventArgs e) 
{   
    IntPtr ptr = IntPtr.Zero; 
    if (LogonUser("USERNAME", "", "LEAVE-THIS-BLANK", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref ptr)) 
    { 
     using (System.Security.Principal.WindowsImpersonationContext context = new System.Security.Principal.WindowsIdentity(ptr).Impersonate()) 
     { 
      try 
      { 
       // Do do something 
      } 
      catch (UnauthorizedAccessException ex) 
      { 
       // failed to do something 
      } 

      // un-impersonate user out 
      context.Undo(); 
     } 
    } 
    else 
    { 
     Response.Write("login fail"); 
    } 
} 

#region imports 

[DllImport("advapi32.dll", SetLastError = true)] 
private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); 

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
private static extern bool CloseHandle(IntPtr handle); 

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
public extern static bool DuplicateToken(IntPtr existingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr duplicateTokenHandle); 

#endregion 

#region logon consts 

// logon types 
const int LOGON32_LOGON_INTERACTIVE = 2; 
const int LOGON32_LOGON_NETWORK = 3; 
const int LOGON32_LOGON_NEW_CREDENTIALS = 9; 

// logon providers 
const int LOGON32_PROVIDER_DEFAULT = 0; 
const int LOGON32_PROVIDER_WINNT50 = 3; 
const int LOGON32_PROVIDER_WINNT40 = 2; 
const int LOGON32_PROVIDER_WINNT35 = 1; 
#endregion } 
Questions connexes