Установка пароля пользователя через System.DirectoryServices.Protocols в AD 2008 R2

Я подключаюсь к серверу Microsoft Active Directory в демилитаризованной зоне из своего приложения .net (asp.net VB .net 4.0). Мне нужно создать нового "inetorgperson" в организации под названием "SingleCustomerAccount".

Мне пришлось использовать пространство имен System.DirectoryServices.Protocols для всей работы, потому что классы ADSI (пространство имен System.DirectoryServices) не работали должным образом в демилитаризованной зоне.

Во всяком случае, подключение к Active Directory на Windows Server 2003 R2 работает нормально; однако мы проводим тесты с Active Directory на Windows Server 2008 R2 (2008r2 в собственном режиме для леса и домена) для обновления.

Мой существующий код для создания пользователя не работает.

System.DirectoryServices.Protocols.DirectoryOperationException: The server cannot handle directory requests.
   at System.DirectoryServices.Protocols.LdapConnection.ConstructResponse(Int32 messageId, LdapOperation operation, ResultAll resultType, TimeSpan requestTimeOut, Boolean exceptionOnTimeOut)
   at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
   at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request)
   at Salford.LDAP.LDAPUser.SaveNewToDirectory(String UsersFirstPassword) in C:\Projects\SCA\App_Code\SCA\LDAPUser.vb:line 1059
   at SCA.Web.Service.CitizenService.CreateNewAccount(String Username, String Title, String FirstName, String Surname, String Street, String City, String County, String Postcode, String EmailAddress, String HomeTel, String MobileTel, String UPRN, String SpinID, Int16 AccountLevel) in C:\Projects\SCA\App_Code\CitizenService.vb:line 255

Я обнаружил, что когда я удаляю фрагмент кода, который добавляет атрибут пароля, создается пользователь, но только без пароля. Таким образом, код ошибки заключается в том, что я добавляю пароль. Но что изменилось между 2003 и 2008 годами, что помешало бы ему работать?

Вот мой код.

Using ldapConn As New LdapConnection(New LdapDirectoryIdentifier(LDAPServerAddress), credential)
 ldapConn.SessionOptions.ProtocolVersion = 3
 ldapConn.SessionOptions.Signing = Not _UseSecureConnection
 ldapConn.SessionOptions.Sealing = Not _UseSecureConnection
 ldapConn.SessionOptions.SecureSocketLayer = _UseSecureConnection
 If _UseSecureConnection Then
  ldapConn.SessionOptions.VerifyServerCertificate = New VerifyServerCertificateCallback(AddressOf ServerCallback)
 End If
 ldapConn.AuthType = AuthType.Negotiate

 ldapConn.Bind()

 Dim DistinguishedName As String = String.Format("CN={0},OU={1},{2}", Me.AccountName, Me.OrgUnit, Me.DCSuffix)

 ' Save this distinguished name to the local object; so that the group memberships addition works in a minute.
 Me._DistinguishedName = DistinguishedName

 Dim addRequest As New AddRequest(DistinguishedName, Me.LDAPUserObjectType)

 '' Add an AccountName attribute
 addRequest.Attributes.Add(New DirectoryAttribute(GetLDAPSchemaMapping(LDAPUserProperties.AccountName), AccountName))

 '' Look in any derived classes, if they want any attributes adding as part of this save operation.

 '' Hint: Derived classes will override the "GetDirectoryAttributesForAddNewRequest" function and return a list of anything they want adding
 '' to the AD at the time of creation.
 If Not GetDirectoryAttributesForAddNewRequest() Is Nothing Then
  For Each kvp As KeyValuePair(Of String, String) In GetDirectoryAttributesForAddNewRequest()
   addRequest.Attributes.Add(New DirectoryAttribute(kvp.Key, kvp.Value))
  Next
 End If

 '' Hash up the password into a Unicode byte array and send this as the requried initial password.
 addRequest.Attributes.Add(New DirectoryAttribute("unicodePwd", GetPasswordData(UsersFirstPassword)))

 ' Execute the request on the directory server.
 Dim addResponse As DirectoryResponse = ldapConn.SendRequest(addRequest)

 ' Need to return the GUID, need to search against the ldap server:
 Dim request As New SearchRequest(String.Format("OU={0},{1}", Me.OrgUnit, Me.DCSuffix), "(&(objectCategory=" & Me.LDAPUserObjectType & ")(sAMAccountName=" & Me.AccountName & "))", System.DirectoryServices.Protocols.SearchScope.Subtree)
 Dim searchResponse As SearchResponse = DirectCast(ldapConn.SendRequest(request), SearchResponse)

 returnedGuid = DirectCast(searchResponse.Entries(0).Attributes("objectGuid").Item(0), Byte())

 ' Set up the search request object so we can do searches now based on this new user:
 Dim rq As SearchRequest = BuildLdapSearchRequest("sAMAccountName", Me.AccountName)

 ' ** Send the query to the LDAP server, and save the response into the private _SearchResponse object **
 _SearchResponse = DirectCast(ldapConn.SendRequest(rq), SearchResponse)
End Using

_useSecureConnection имеет значение false для этого вызова — привязка работает нормально. Как я уже сказал, когда я комментирую эту строку, она работает:

addRequest.Attributes.Add(New DirectoryAttribute("unicodePwd", GetPasswordData(UsersFirstPassword)))

Метод GetPasswordData приведен ниже для полноты картины.

''' <summary>
''' Returns a unicode-encoded byte array based on the incoming password string.
''' </summary>
''' <param name="password">The password to turn into a byte array</param>
Public Function GetPasswordData(ByVal password As String) As Byte()
 Dim formattedPassword As String
 formattedPassword = String.Format("""{0}""", password)
 Return Encoding.Unicode.GetBytes(formattedPassword)
End Function

Я ценю любые идеи...

С уважением bgs264


person bgs264    schedule 29.06.2010    source источник


Ответы (2)


Возможно ли, что политики паролей различаются для двух серверов? Или что есть какое-то другое различие в политике?

Одним из способов проверки может быть использование инструмента ldp.exe и проверка возможности выполнения с ним тех же операций с точно таким же паролем. Здесь ссылка, описывающая изменение пароль с помощью этого инструмента.

person Hans Olsson    schedule 29.06.2010
comment
Спасибо за ответ. Пароль действителен, потому что это надежный пароль, и с помощью оснастки «Пользователи Active Directory» пароль можно установить, как и ожидалось. Я пытался следовать учебнику, на который вы дали ссылку. Процесс работает, но там, где он указывает изменить атрибут userpassword, я думаю, что это неприменимо - он не меняет пароль - он просто добавляет атрибут с тем, что вы указываете. Затем вы можете распечатать его обратно, что кажется неправильным: 1> почтовый индекс: BL4 1RR; 1>пароль пользователя: ben; 1› данноеИмя: Бен; Также не меняется пароль от учетной записи. С уважением, Бен - person bgs264; 29.06.2010
comment
Хм, я думаю, проблема может заключаться в том, что учебник относится к службам Active Directory облегченного доступа к каталогам, тогда как это обычная Active Directory. Но спасибо за идею. - person bgs264; 29.06.2010
comment
@bgs264: Если бы вы могли установить точно такой же пароль с любым паролем для этого домена, то это, вероятно, достаточное доказательство того, что моя догадка была неверной, и я не думаю, что вам нужно беспокоиться о ldp (я не использовал его в течение длительного времени и не могу вспомнить, как это работает в любом случае). - person Hans Olsson; 29.06.2010

Это было исправлено комбинацией использования LDAPS вместо LDAP; смягчение политики паролей; сделать полную перестройку приложения; очистка кеша браузера и перезагрузка всех серверов.

person bgs264    schedule 30.06.2010
comment
Одним из примеров несоблюдения политики паролей является установка минимального срока действия пароля (1-2 дня) и сброс пароля недавно, то есть непосредственно перед тестированием. Вы должны дождаться полного соблюдения политики паролей, прежде чем ваш пароль будет разрешено изменить! Кроме того, убедитесь, что вы соответствуете требованиям сложности (не используйте свое имя/фамилию в пароле, строчные и прописные буквы, цифры, символы, минимальную длину). LDAP/AD действительно нуждается в лучшем ответе на ошибку, чем эта общая ошибка! DirectoryOperationException: The server cannot handle directory requests - person Nigel Sheridan-Smith; 21.08.2020