using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.DirectoryServices; using System.DirectoryServices.Protocols; using System.Linq; using System.Net; using System.Security.Cryptography.X509Certificates; using System.Text; namespace FineUIPro.Web { public sealed class LdapAuthentication { private bool _allowAnyCertificates; private string _domain; private string _path; private string _userNameProxyUser; private string _passwordProxyUser; private AuthenticationTypes _authenticationType; public static readonly string LdapUriString = "LDAP"; public static readonly int LdapPort = 389; public static readonly int LdapPortSsl = 636; private X509Certificate _locallyVerificationCertificate; private string _locallyVerificationCertificateSerialNumber; private bool _useSecureSocketLayer; private bool _verifyCertificateLocally; private LdapDirectoryIdentifier _directoryIdentifier; public bool AllowAnyCertificates { get { return _allowAnyCertificates; } set { _allowAnyCertificates = value; } } public string Domain { get { return _domain; } set { _domain = value; } } public string Path { get { return _path; } set { _path = value; } } public string UserNameProxyUser { get { return _userNameProxyUser; } set { _userNameProxyUser = value; } } public string PasswordProxyUser { get { return _passwordProxyUser; } set { _passwordProxyUser = value; } } public AuthenticationTypes AuthenticationType { get { return _authenticationType; } set { _authenticationType = value; } } public X509Certificate LocallyVerificationCertificate { get { return _locallyVerificationCertificate; } set { _locallyVerificationCertificate = value; } } public string LocallyVerificationCertificateSerialNumber { get { return _locallyVerificationCertificateSerialNumber; } set { _locallyVerificationCertificateSerialNumber = value; } } public bool UseSecureSocketLayer { get { return _useSecureSocketLayer; } set { lock (this) { _useSecureSocketLayer = value; } } } public bool VerifyCertificateLocally { get { return _verifyCertificateLocally; } set { lock (this) { _verifyCertificateLocally = value; } } } public LdapDirectoryIdentifier DirectoryIdentifier { get { if (_directoryIdentifier == null) { lock (this) { SetDirectoryIdentifier(); } } return _directoryIdentifier; } } public LdapAuthentication() { _authenticationType = AuthenticationTypes.FastBind; } private void SetDirectoryIdentifier() { int num = 0; _directoryIdentifier = new LdapDirectoryIdentifier(portNumber: (!UseSecureSocketLayer) ? LdapPort : LdapPortSsl, server: _domain); } public DirectoryEntry GetDirectoryEntryOfProxyUser() { string text = $"{LdapUriString}://{_domain}/{_path}"; using (DirectoryEntry result = new DirectoryEntry(text, _userNameProxyUser, _passwordProxyUser, _authenticationType)) { try { return result; } catch (Exception innerException) { throw new Exception(text, innerException); } } } private bool OnLdapConnectionVerifyServerCertificate(LdapConnection connection, X509Certificate serverCertificate) { if (AllowAnyCertificates) { return true; } if (!VerifyCertificateLocally) { return true; } if (LocallyVerificationCertificate != null) { if (LocallyVerificationCertificate.Equals(serverCertificate)) { return true; } return false; } if (!string.IsNullOrEmpty(LocallyVerificationCertificateSerialNumber)) { if (serverCertificate.GetSerialNumberString() == LocallyVerificationCertificateSerialNumber) { return true; } return false; } X509Store x509Store = new X509Store("My"); x509Store.Open(OpenFlags.ReadOnly); X509Certificate2Enumerator enumerator = x509Store.Certificates.GetEnumerator(); while (enumerator.MoveNext()) { X509Certificate2 current = enumerator.Current; if (current.SerialNumber == serverCertificate.GetSerialNumberString()) { return true; } } return false; } public bool CheckPassword(string userName, string password) { Collection groupMemberships = null; LdapUser ldapUserInfo = null; return CheckPassword(userName, password, readGroupMemberships: false, out groupMemberships, readLdapUserInfo: false, out ldapUserInfo); } public bool CheckPassword(string userName, string password, out Collection groupMemberships) { LdapUser ldapUserInfo = null; return CheckPassword(userName, password, readGroupMemberships: true, out groupMemberships, readLdapUserInfo: false, out ldapUserInfo); } public bool CheckPassword(string userName, string password, out LdapUser ldapUserInfo) { Collection groupMemberships = null; return CheckPassword(userName, password, readGroupMemberships: false, out groupMemberships, readLdapUserInfo: true, out ldapUserInfo); } public bool CheckPassword(string userName, string password, out Collection groupMemberships, out LdapUser ldapUserInfo) { return CheckPassword(userName, password, readGroupMemberships: true, out groupMemberships, readLdapUserInfo: true, out ldapUserInfo); } private bool CheckPassword(string userName, string password, bool readGroupMemberships, out Collection groupMemberships, bool readLdapUserInfo, out LdapUser ldapUserInfo) { if (string.IsNullOrEmpty(userName)) { throw new ArgumentNullException("userName"); } if (string.IsNullOrEmpty(password)) { throw new ArgumentNullException("password"); } if (password.Length >= 128) { throw new Exception(); } groupMemberships = null; ldapUserInfo = null; List list = new List(); DirectoryEntry directoryEntryOfProxyUser = GetDirectoryEntryOfProxyUser(); if (directoryEntryOfProxyUser == null) { throw new Exception(); } lock (this) { BLL.ErrLogInfo.WriteLog("lock锁这里"); using (LdapConnection ldapConnection = new LdapConnection(DirectoryIdentifier)) { try { BLL.ErrLogInfo.WriteLog("ldap验证"); ldapConnection.SessionOptions.SecureSocketLayer = UseSecureSocketLayer; if (UseSecureSocketLayer && (AllowAnyCertificates || VerifyCertificateLocally)) { LdapSessionOptions sessionOptions = ldapConnection.SessionOptions; sessionOptions.VerifyServerCertificate = (VerifyServerCertificateCallback)Delegate.Combine(sessionOptions.VerifyServerCertificate, new VerifyServerCertificateCallback(OnLdapConnectionVerifyServerCertificate)); } ldapConnection.Credential = new NetworkCredential(UserNameProxyUser, PasswordProxyUser); ldapConnection.AuthType = AuthType.Basic; ldapConnection.SessionOptions.ProtocolVersion = 3; ldapConnection.Bind(); } catch (DirectoryServicesCOMException innerException) { BLL.ErrLogInfo.WriteLog($"ldap验证失败:{innerException.Message}"); throw new Exception("Proxyuser_NotFound", innerException); } catch (Exception ex) { BLL.ErrLogInfo.WriteLog($"捕获异常信息:{ex.Message}"); throw ex; } finally { if (UseSecureSocketLayer && (AllowAnyCertificates || VerifyCertificateLocally)) { LdapSessionOptions sessionOptions2 = ldapConnection.SessionOptions; sessionOptions2.VerifyServerCertificate = (VerifyServerCertificateCallback)Delegate.Remove(sessionOptions2.VerifyServerCertificate, new VerifyServerCertificateCallback(OnLdapConnectionVerifyServerCertificate)); } } string ldapFilter = $" (cn={userName})"; if (readGroupMemberships) { list.Add("groupmembership"); } if (readLdapUserInfo) { BLL.ErrLogInfo.WriteLog($"readLdapUserInfo信息:{readLdapUserInfo}"); GetUserAttrs(list); } SearchRequest request = new SearchRequest(_path, ldapFilter, System.DirectoryServices.Protocols.SearchScope.Subtree, list.ToArray()); SearchResponse searchResponse = (SearchResponse)ldapConnection.SendRequest(request); if (searchResponse == null || searchResponse.Entries == null || searchResponse.Entries.Count < 1) { throw new Exception(); } BLL.ErrLogInfo.WriteLog($"searchResponse不等于空"); SearchResultEntry searchResultEntry = searchResponse.Entries[0]; string distinguishedName = searchResultEntry.DistinguishedName; BLL.ErrLogInfo.WriteLog($"distinguishedName={distinguishedName}"); if (readGroupMemberships) { groupMemberships = ReadGroupMembershipsInternal(searchResultEntry); } if (readLdapUserInfo) { ldapUserInfo = GetUserInfoFromDirectoryEntry(searchResultEntry); } ldapConnection.Credential = new NetworkCredential(distinguishedName, password); try { ldapConnection.Bind(); } catch (LdapException innerException2) { BLL.ErrLogInfo.WriteLog($"ldap错误={innerException2.Message}"); throw new Exception("LdapAuthentication_WrongPassword", innerException2); } return true; } } } private static void GetUserAttrs(List attrs) { attrs.Add("basfANRED"); attrs.Add("basfBuilding"); attrs.Add("basfCCCompany"); attrs.Add("basfCCPN"); attrs.Add("basfCompanyID"); attrs.Add("basfContractStatus"); attrs.Add("basfCostCenter"); attrs.Add("basfEPSapGroup"); attrs.Add("basfEPSapUserID"); attrs.Add("basfCCPN"); attrs.Add("basfGCDID"); attrs.Add("basfIDtype"); attrs.Add("basfPersg"); attrs.Add("basfPersonID"); attrs.Add("basfRegion"); attrs.Add("basfRPID"); attrs.Add("basfSBNR"); attrs.Add("basfSex"); attrs.Add("basfSIAMID"); attrs.Add("dn"); attrs.Add("cn"); attrs.Add("uid"); attrs.Add("co"); attrs.Add("employeeStatus"); attrs.Add("facsimileTelephoneNumber"); attrs.Add("fullName"); attrs.Add("givenName"); attrs.Add("GroupMembership"); attrs.Add("InternetEmailAddress"); attrs.Add("l"); attrs.Add("mobile"); attrs.Add("o"); attrs.Add("ou"); attrs.Add("postalCode"); attrs.Add("roomNumber"); attrs.Add("s"); attrs.Add("sa"); attrs.Add("surname"); attrs.Add("telephoneNumber"); attrs.Add("title"); attrs.Add("mail"); attrs.Add("sn"); attrs.Add("employeeNumber"); attrs.Add("basfUDMSID"); attrs.Add("postalAddress"); attrs.Add("c"); } private static LdapUser GetUserInfoFromDirectoryEntry(SearchResultEntry entry) { LdapUser ldapUser = new LdapUser(); if (entry.Attributes.Contains("cn")) { ldapUser.UserName = (string)entry.Attributes["cn"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("mail")) { ldapUser.EmailAddress = (string)entry.Attributes["mail"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("givenName")) { ldapUser.FirstName = (string)entry.Attributes["givenName"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("sn")) { ldapUser.LastName = (string)entry.Attributes["sn"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("fullName")) { ldapUser.FullName = (string)entry.Attributes["fullName"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("o")) { ldapUser.Company = (string)entry.Attributes["o"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("ou")) { ldapUser.OrgCode = (string)entry.Attributes["ou"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("telephoneNumber")) { ldapUser.Phone = (string)entry.Attributes["telephoneNumber"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("basfGCDID")) { ldapUser.GcdId = (string)entry.Attributes["basfGCDID"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("basfPersonID")) { ldapUser.PersonId = (string)entry.Attributes["basfPersonID"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("employeeNumber")) { ldapUser.PersonalNr = (string)entry.Attributes["employeeNumber"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("basfCCPN")) { ldapUser.Ccpn = (string)entry.Attributes["basfCCPN"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("basfUDMSID")) { ldapUser.UdmsId = (string)entry.Attributes["basfUDMSID"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("postalAddress")) { ldapUser.Street = (string)entry.Attributes["postalAddress"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("l")) { ldapUser.City = (string)entry.Attributes["l"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("postalCode")) { ldapUser.ZipCode = (string)entry.Attributes["postalCode"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("c")) { ldapUser.Country = (string)entry.Attributes["c"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("facsimileTelephoneNumber")) { ldapUser.Fax = (string)entry.Attributes["facsimileTelephoneNumber"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("mobile")) { ldapUser.MobilePhone = (string)entry.Attributes["mobile"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("basfcompanyid")) { ldapUser.CompanyId = (string)entry.Attributes["basfcompanyid"].GetValues(typeof(string))[0]; } if (entry.Attributes.Contains("basfidtype")) { ldapUser.BasfIdType = (string)entry.Attributes["basfidtype"].GetValues(typeof(string))[0]; } return ldapUser; } private static Collection ReadGroupMembershipsInternal(SearchResultEntry entry) { Collection collection = new Collection(); object[] values = entry.Attributes["groupmembership"].GetValues(typeof(string)); for (int i = 0; i < values.Length; i++) { string item = (string)values[i]; collection.Add(item); } return collection; } private static LdapUser GetUserInfoFromSearchResult(DirectoryEntry entry) { LdapUser ldapUser = new LdapUser(); if (entry.Properties.Contains("cn")) { ldapUser.UserName = entry.Properties["cn"].Value.ToString(); } if (entry.Properties.Contains("mail")) { ldapUser.EmailAddress = entry.Properties["mail"].Value.ToString(); } if (entry.Properties.Contains("givenName")) { ldapUser.FirstName = entry.Properties["givenName"].Value.ToString(); } if (entry.Properties.Contains("sn")) { ldapUser.LastName = entry.Properties["sn"].Value.ToString(); } if (entry.Properties.Contains("fullName")) { ldapUser.FullName = entry.Properties["fullName"].Value.ToString(); } if (entry.Properties.Contains("o")) { ldapUser.Company = entry.Properties["o"].Value.ToString(); } if (entry.Properties.Contains("ou")) { ldapUser.OrgCode = entry.Properties["ou"].Value.ToString(); } if (entry.Properties.Contains("telephoneNumber")) { ldapUser.Phone = entry.Properties["telephoneNumber"].Value.ToString(); } if (entry.Properties.Contains("basfGCDID")) { ldapUser.GcdId = entry.Properties["basfGCDID"].Value.ToString(); } if (entry.Properties.Contains("basfPersonID")) { ldapUser.PersonId = entry.Properties["basfPersonID"].Value.ToString(); } if (entry.Properties.Contains("employeeNumber")) { ldapUser.PersonalNr = entry.Properties["employeeNumber"].Value.ToString(); } if (entry.Properties.Contains("basfCCPN")) { ldapUser.Ccpn = entry.Properties["basfCCPN"].Value.ToString(); } if (entry.Properties.Contains("basfUDMSID")) { ldapUser.UdmsId = entry.Properties["basfUDMSID"].Value.ToString(); } if (entry.Properties.Contains("postalAddress")) { ldapUser.Street = entry.Properties["postalAddress"].Value.ToString(); } if (entry.Properties.Contains("l")) { ldapUser.City = entry.Properties["l"].Value.ToString(); } if (entry.Properties.Contains("postalCode")) { ldapUser.ZipCode = entry.Properties["postalCode"].Value.ToString(); } if (entry.Properties.Contains("c")) { ldapUser.Country = entry.Properties["c"].Value.ToString(); } if (entry.Properties.Contains("facsimileTelephoneNumber")) { ldapUser.Fax = entry.Properties["facsimileTelephoneNumber"].Value.ToString(); } if (entry.Properties.Contains("mobile")) { ldapUser.MobilePhone = entry.Properties["mobile"].Value.ToString(); } if (entry.Properties.Contains("basfcompanyid")) { ldapUser.CompanyId = entry.Properties["basfcompanyid"].Value.ToString(); } if (entry.Properties.Contains("basfidtype")) { ldapUser.BasfIdType = entry.Properties["basfidtype"].Value.ToString(); } return ldapUser; } } }