【问题标题】:Update Active Directory account information from asp.net and SQL server从 asp.net 和 SQL 服务器更新 Active Directory 帐户信息
【发布时间】:2015-09-04 06:38:32
【问题描述】:

我需要开发一个更新功能(asp.net web 应用程序),定期从我们的人力资源数据库(sql server)更新活动目录(AD)信息(例如职位)

我可以成功地从 AD 中检索数据。但是当我运行更新函数时,它返回以下错误:

一般访问被拒绝错误

描述:执行过程中发生了未处理的异常 当前的网络请求。请查看堆栈跟踪以获取更多信息 有关错误的信息以及它在代码中的来源。

异常详细信息:System.UnauthorizedAccessException:一般访问 拒绝错误

ASP.NET 无权访问请求的资源。考虑 向 ASP.NET 请求授予对资源的访问权限 身份。 ASP.NET 有一个基本进程标识(通常 IIS 5 上的 {MACHINE}\ASPNET 或 IIS 6 上的网络服务),如果 该应用程序不是模拟的。如果应用程序是 冒充 via ,身份将是 匿名用户(通常是 IUSR_MACHINENAME)或经过身份验证的用户 请求用户。

要授予 ASP.NET 对文件的访问权限,请在资源管理器中右键单击该文件, 选择“属性”并选择“安全”选项卡。点击“添加”添加 适当的用户或组。突出显示 ASP.NET 帐户,然后 选中所需访问权限的复选框。

我已确认我使用的用户帐户 (AD) 已拥有更新权限。 在sql management studio中,已经搭建了一个ADSI Linked server到AD。

但仍然不知道如何解决问题。

感谢您的帮助。谢谢。

以下是我的代码:

Imports System.Text
Imports System.DirectoryServices
Imports System.DirectoryServices.AccountManagement
Imports System.Security.Principal

Partial Class Scheduler_AutoUpdate_AD
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Server.ScriptTimeout = 2400
    End Sub

    Protected Sub btnSubmit_Click(sender As Object, e As EventArgs)

        ReadAD()
        UpdateAD()

    End Sub


    Sub UpdateAD()       
        Dim de As New DirectoryEntry()
        Dim connection As String = ConfigurationManager.ConnectionStrings("ADConnectionString2").ToString()

        Dim dssearch As New DirectorySearcher(connection)

        dssearch.Filter = "(&(objectClass=user)(SAMAccountName=" & txtusername.Text & "))"
        Dim sresult As SearchResult = dssearch.FindOne()
        Dim dsresult As DirectoryEntry = sresult.GetDirectoryEntry()
        'dsresult.Properties("company").Value = "Test1"
        dsresult.Properties("manager").Value = "Test1"
        dsresult.CommitChanges()
        dsresult.Close()

    End Sub

    Sub ReadAD()

        Dim de As New DirectoryEntry()

        Dim connection As String = ConfigurationManager.ConnectionStrings("ADConnectionString2").ToString()
        Dim dssearch As New DirectorySearcher(connection)
        dssearch.Filter = "(&(objectClass=user)(sAMAccountName=" & txtusername.Text & "))"
        Dim sresult As SearchResult = dssearch.FindOne()
        Dim dsresult As DirectoryEntry = sresult.GetDirectoryEntry()

        lblfname.Text = dsresult.Properties("givenName")(0).ToString()
        lbllname.Text = dsresult.Properties("sn")(0).ToString()
        lblemail.Text = dsresult.Properties("mail")(0).ToString()
        lblusername.Text = dsresult.Properties("sAMAccountName")(0).ToString()
        lblipphone.Text = dsresult.Properties("ipPhone")(0).ToString()
        lblusergroup.Text = dsresult.Properties("memberof")(0).ToString()
        lbljobtitle.Text = dsresult.Properties("title")(0).ToString()

    End Sub


End Class

【问题讨论】:

    标签: asp.net sql-server vb.net active-directory ldap


    【解决方案1】:

    您可以使用用户模拟:使用允许执行此类操作的用户的凭据,您可以使 ASP.NET 应用程序充当具有更高权限的用户。
    您可以将这些凭据保存在配置文件中(恕我直言不安全,因为是管理员凭据)或在访问页面时以交互方式要求用户使用它们。

    这里按照我在网上找到的任务代码(我不记得来源,这不是我的工作):

    Public Enum LogonType
        LOGON32_LOGON_INTERACTIVE = 2
        LOGON32_LOGON_NETWORK = 3
        LOGON32_LOGON_BATCH = 4
        LOGON32_LOGON_SERVICE = 5
        LOGON32_LOGON_UNLOCK = 7
        LOGON32_LOGON_NETWORK_CLEARTEXT = 8
        ' Win2K or higher
        LOGON32_LOGON_NEW_CREDENTIALS = 9
        ' Win2K or higher
    End Enum
    
    Public Enum LogonProvider
        LOGON32_PROVIDER_DEFAULT = 0
        LOGON32_PROVIDER_WINNT35 = 1
        LOGON32_PROVIDER_WINNT40 = 2
        LOGON32_PROVIDER_WINNT50 = 3
    End Enum
    
    Public Enum ImpersonationLevel
        SecurityAnonymous = 0
        SecurityIdentification = 1
        SecurityImpersonation = 2
        SecurityDelegation = 3
    End Enum
    
    Class Win32NativeMethods
        <DllImport("advapi32.dll", SetLastError:=True)> _
        Public Shared Function LogonUser(lpszUserName As String, lpszDomain As String, lpszPassword As String, dwLogonType As Integer, dwLogonProvider As Integer, ByRef phToken As IntPtr) As Integer
        End Function
    
        <DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function DuplicateToken(hToken As IntPtr, impersonationLevel As Integer, ByRef hNewToken As IntPtr) As Integer
        End Function
    
        <DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function RevertToSelf() As Boolean
        End Function
    
        <DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
        Public Shared Function CloseHandle(handle As IntPtr) As Boolean
        End Function
    End Class
    ''' <summary>
    ''' Allows code to be executed under the security context of a specified user account.
    ''' </summary>
    ''' <remarks> 
    '''
    ''' Implements IDispose, so can be used via a using-directive or method calls;
    '''  ...
    '''
    '''  var imp = new Impersonator( "myUsername", "myDomainname", "myPassword" );
    '''  imp.UndoImpersonation();
    '''
    '''  ...
    '''
    '''   var imp = new Impersonator();
    '''  imp.Impersonate("myUsername", "myDomainname", "myPassword");
    '''  imp.UndoImpersonation();
    '''
    '''  ...
    '''
    '''  using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
    '''  {
    '''   ...
    '''   1
    '''   ...
    '''  }
    '''
    '''  ...
    ''' </remarks>
    Public Class Impersonator
        Implements IDisposable
        Private _wic As WindowsImpersonationContext
    
    ''' <summary>
    ''' Begins impersonation with the given credentials, Logon type and Logon provider.
    ''' </summary>
    ''' <param name="userName">Name of the user.</param>
    ''' <param name="domainName">Name of the domain.</param>
    ''' <param name="password">The password. <see cref="System.String"/></param>
    ''' <param name="logonType">Type of the logon.</param>
    ''' <param name="logonProvider">The logon provider.</param>
    Public Sub New(userName As String, domainName As String, password As String, logonType As LogonType, logonProvider As LogonProvider)
        Impersonate(userName, domainName, password, logonType, logonProvider)
    End Sub
    
    ''' <summary>
    ''' Begins impersonation with the given credentials.
    ''' </summary>
    ''' <param name="userName">Name of the user.</param>
    ''' <param name="domainName">Name of the domain.</param>
    ''' <param name="password">The password. <see cref="System.String"/></param>
    Public Sub New(userName As String, domainName As String, password As String)
        Impersonate(userName, domainName, password, LogonType.LOGON32_LOGON_INTERACTIVE, LogonProvider.LOGON32_PROVIDER_DEFAULT)
    End Sub
    
    ' <summary>
    ' Initializes a new instance of the <see cref="Impersonator"/> class.
    ' </summary>
    'public Impersonator()
    '{ }
    
    ''' <summary>
    ''' Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    ''' </summary>
    Public Sub Dispose() Implements IDisposable.Dispose
        UndoImpersonation()
    End Sub
    
    ''' <summary>
    ''' Impersonates the specified user account.
    ''' </summary>
    ''' <param name="userName">Name of the user.</param>
    ''' <param name="domainName">Name of the domain.</param>
    ''' <param name="password">The password. <see cref="System.String"/></param>
    Public Sub Impersonate(userName As String, domainName As String, password As String)
        Impersonate(userName, domainName, password, LogonType.LOGON32_LOGON_INTERACTIVE, LogonProvider.LOGON32_PROVIDER_DEFAULT)
    End Sub
    
    ''' <summary>
    ''' Impersonates the specified user account.
    ''' </summary>
    ''' <param name="userName">Name of the user.</param>
    ''' <param name="domainName">Name of the domain.</param>
    ''' <param name="password">The password. <see cref="System.String"/></param>
    ''' <param name="logonType">Type of the logon.</param>
    ''' <param name="logonProvider">The logon provider.</param>
    Public Sub Impersonate(userName As String, domainName As String, password As String, logonType As LogonType, logonProvider As LogonProvider)
        UndoImpersonation()
    
        Dim logonToken As IntPtr = IntPtr.Zero
        Dim logonTokenDuplicate As IntPtr = IntPtr.Zero
        Try
            ' revert to the application pool identity, saving the identity of the current requestor
            _wic = WindowsIdentity.Impersonate(IntPtr.Zero)
    
            ' do logon & impersonate
            If Win32NativeMethods.LogonUser(userName, domainName, password, CInt(logonType), CInt(logonProvider), logonToken) <> 0 Then
                If Win32NativeMethods.DuplicateToken(logonToken, CInt(ImpersonationLevel.SecurityImpersonation), logonTokenDuplicate) <> 0 Then
                    Dim wi = New WindowsIdentity(logonTokenDuplicate)
                    ' discard the returned identity context (which is the context of the application pool)
                    wi.Impersonate()
                Else
                    Throw New Win32Exception(Marshal.GetLastWin32Error())
                End If
            Else
                Throw New Win32Exception(Marshal.GetLastWin32Error())
            End If
        Finally
            If logonToken <> IntPtr.Zero Then
                Win32NativeMethods.CloseHandle(logonToken)
            End If
    
            If logonTokenDuplicate <> IntPtr.Zero Then
                Win32NativeMethods.CloseHandle(logonTokenDuplicate)
            End If
        End Try
    End Sub
    
    ''' <summary>
    ''' Stops impersonation.
    ''' </summary>
    Private Sub UndoImpersonation()
        ' restore saved requestor identity
        If _wic IsNot Nothing Then
            _wic.Undo()
        End If
        _wic = Nothing
    End Sub
    End Class
    

    如何使用:

        Using imp As Tools.Network.Impersonator = New Network.Impersonator(username, domain, password)
            ' the code that requires privileges goes here
            ' also initialization of objects that requires permission MUST be inside the USING,
            ' objects initialized outside this scope will not be affected
        End Using
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-02
      • 1970-01-01
      相关资源
      最近更新 更多