出现一个操作错误 (An operations error occurred)

 问题描述:

 出现一个操作错误  An operations error occurred

--> System.Runtime.InteropServices.COMException (0x80072020): An operations error occurred.

 

Server stack trace:
  at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
  at System.DirectoryServices.DirectoryEntry.Bind()
  at System.DirectoryServices.DirectoryEntry.get_AdsObject()
  at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
  at System.DirectoryServices.DirectorySearcher.FindAll()

 

问题原因:

在访问(Active Directory)活动目录时的安全性有关。

详见:http://support.microsoft.com/kb/329986/zh-cn

通常在不进行角色模拟的情况下,访问本地(localAD是没有问题的;但是如果访问服务器的AD时,就会出现“出现一个操作错误”。用角色模拟就可以解决。

 

解决方案一:

public class IdentityImpersonation

    {

        /// <summary>

        /// Logons the user.

        /// </summary>

        /// <param name="lpszUsername">The LPSZ username.</param>

        /// <param name="lpszDomain">The LPSZ domain.</param>

        /// <param name="lpszPassword">The LPSZ password.</param>

        /// <param name="dwLogonType">Type of the dw logon.</param>

        /// <param name="dwLogonProvider">The dw logon provider.</param>

        /// <param name="phToken">The ph token.</param>

        /// <returns></returns>

        [DllImport("advapi32.dll", SetLastError = true)]

        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

 

        /// <summary>

        /// Duplicates the token.

        /// </summary>

        /// <param name="ExistingTokenHandle">The existing token handle.</param>

        /// <param name="SECURITY_IMPERSONATION_LEVEL">The SECURIT y_ IMPERSONATIO n_ LEVEL.</param>

        /// <param name="DuplicateTokenHandle">The duplicate token handle.</param>

        /// <returns></returns>

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]

        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

 

        /// <summary>

        /// Closes the handle.

        /// </summary>

        /// <param name="handle">The handle.</param>

        /// <returns></returns>

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]

        public extern static bool CloseHandle(IntPtr handle);

 

        // 要模拟的用户的用户名、密码、域(机器名)

        private String _sImperUsername;

        private String _sImperPassword;

        private String _sImperDomain;

 

        //记录模拟上下文

        private WindowsImpersonationContext _imperContext;

        private IntPtr _adminToken;

        private IntPtr _dupeToken;

 

        // 是否已停止模拟

        private Boolean _bClosed;

 

        /// <summary>

        /// 构造函数

        /// </summary>

        /// <param name="impersonationUsername">所要模拟的用户的用户名</param>

        /// <param name="impersonationPassword">所要模拟的用户的密码</param>

        /// <param name="impersonationDomain">所要模拟的用户所在的域</param>

        public IdentityImpersonation(String impersonationUsername, String impersonationPassword, String impersonationDomain)

        {

            _sImperUsername = impersonationUsername;

            _sImperPassword = impersonationPassword;

            _sImperDomain = impersonationDomain;

            _adminToken = IntPtr.Zero;

            _dupeToken = IntPtr.Zero;

            _bClosed = true;

        }

 

        /// <summary>

        /// 析构函数

        /// </summary>

        ~IdentityImpersonation()

        {

            if (!_bClosed)

            {

                StopImpersonate();

            }

        }

 

        /// <summary>

        /// 开始身份角色模拟。

        /// </summary>

        /// <returns></returns>

        public Boolean BeginImpersonate()

        {

            Boolean bLogined = LogonUser(_sImperUsername, _sImperDomain, _sImperPassword, 2, 0, ref _adminToken);

            if (!bLogined)

            {

                return false;

            }

 

            Boolean bDuped = DuplicateToken(_adminToken, 2, ref _dupeToken);

            if (!bDuped)

            {

                return false;

            }

 

            WindowsIdentity fakeId = new WindowsIdentity(_dupeToken);

            _imperContext = fakeId.Impersonate();

            _bClosed = false;

 

            return true;

        }

 

        /// <summary>

        /// 停止身分角色模拟。

        /// </summary>

        public void StopImpersonate()

        {

            //_imperContext.Undo();

 

            CloseHandle(_dupeToken);

            CloseHandle(_adminToken);

            _bClosed = true;

        }

 

    }

 

但是用这种方法模拟时要注意:

public static IdentityImpersonation impersonate = new IdentityImpersonation(ADUser, ADPassword, ADDomain);

在模拟时,账户格式:domain\loginname.

  <appSettings>

    <!-- ADPath的格式,必须严格按照下面的格式 -->

    <add key="ADPath" value="LDAP://OU=ou,DC=domain,DC=com"/>

    <add key="ADAdminUser" value="domain\administrator"/>

    <add key="ADPassword" value="123-aaa"/>

    <add key="ADDomain" value="domain.com"/>

    <!-- ImageUrl -->

  </appSettings>

 

如果账户不对或LDAP有误,将会出项“没有注册类别”的错误

 

解决方案二:

using System.Web.Hosting;
...
...

// Code here runs as the logged on user

using (HostingEnvironment.Impersonate()) {
// This code runs as the application pool user
     DirectorySearcher searcher ...
}

// Code here runs as logged on user again

但是,这种方法也存在不足,

详见:http://msdn.microsoft.com/en-us/library/system.web.hosting.hostingenvironment.impersonate.aspx

 

Name

Description

Impersonate()

Impersonates the user represented by the application identity.

Impersonate(IntPtr)

Impersonates the user represented by the specified user token.

Impersonate(IntPtr, String)

Impersonates the user specified by the configuration settings for the specified virtual path, or the specified user token.

 

解决方案三:

           using (DirectoryEntry entry = new DirectoryEntry(strPath, ADUser, ADPassword, AuthenticationTypes.Secure))

            {

                using (System.DirectoryServices.DirectorySearcher mySearcher = new System.DirectoryServices.DirectorySearcher(entry))

                {

                    // code here

                }

            }

直接用域用户的帐号来获得entry

原文地址:https://www.cnblogs.com/LeimOO/p/1377485.html