进行模拟后无法获取访问控制,出现错误
Posted
技术标签:
【中文标题】进行模拟后无法获取访问控制,出现错误【英文标题】:Can't GetAccessControl After Doing Impersonation, Get Error 【发布时间】:2014-02-17 22:28:42 【问题描述】:我需要能够使用具有更高权限的帐户更改文件的访问权限。这是我的模拟代码:
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_PROVIDER_DEFAULT = 0;
public Impersonation(string domain, string username, string password)
var ok = LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out this._handle);
if (!ok)
var errorCode = Marshal.GetLastWin32Error();
throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code 0.", errorCode));
this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
public void Dispose()
this._context.Dispose();
this._handle.Dispose();
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
private SafeTokenHandle()
: base(true)
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
return CloseHandle(handle);
这是使用模拟的 sn-p:
using (new Impersonation("domain", "username", "pswd"))
FileInfo fi = new FileInfo(@"file name");
FileSecurity fs = fi.GetAccessControl();
这是我尝试执行 GetAccessControl 时得到的结果。任何帮助将不胜感激。
System.InvalidOperationException: Method failed with unexpected error code 3.
at System.Security.AccessControl.NativeObjectSecurity.CreateInternal(Resource
Type resourceType, Boolean isContainer, String name, SafeHandle handle, AccessCo
ntrolSections includeSections, Boolean createByName, ExceptionFromErrorCode exce
ptionFromErrorCode, Object exceptionContext)
at System.Security.AccessControl.FileSystemSecurity..ctor(Boolean isContainer
, String name, AccessControlSections includeSections, Boolean isDirectory)
at System.Security.AccessControl.FileSecurity..ctor(String fileName, AccessCo
ntrolSections includeSections)
at System.IO.FileInfo.GetAccessControl()
at ImpersonationDemo.Main(String[] args) in c:\Users\david.ohara\Documents\Vi
sual Studio 2013\Projects\SecTest\SecTest\Program.cs:line 84
【问题讨论】:
【参考方案1】:我以前做过,但它是在 VB.net 中而不是 C# 中,但代码可能会对你有所帮助,因为这肯定有效:
在伪代码中是:
LogonUserA(userName, domain, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, token)
DuplicateToken(token, 2, tokenDuplicate)
_windowsIdentity = New WindowsIdentity(tokenDuplicate)
_impersonationContext = _windowsIdentity.Impersonate()
System.Threading.Thread.CurrentPrincipal = New System.Security.Principal.WindowsPrincipal(_windowsIdentity)
这是一个完整的类。它位于 VB.Net 中,因此您需要将其转换为 C#:
Option Strict On
#Region "Imports"
Imports System.Security.Principal
Imports System.Runtime.InteropServices
Imports System
Imports System.Net
Imports System.Net.Security
Imports System.Security
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports System.IO
Imports System.Security.Cryptography
#End Region
Public Class ABCSecurity
#Region "Members"
Private Shared _impersonationContext As WindowsImpersonationContext
Private Shared _windowsIdentity As WindowsIdentity
#End Region
#Region "Win32 APIs"
Private Shared LOGON32_LOGON_INTERACTIVE As Integer = 2
Private Shared LOGON32_PROVIDER_DEFAULT As Integer = 0
Private Shared LOGON32_LOGON_BATCH As Integer = 4
Private Shared LOGON32_LOGON_NETWORK As Integer = 3
Private Declare Function LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, _
ByVal lpszDomain As String, _
ByVal lpszPassword As String, _
ByVal dwLogonType As Integer, _
ByVal dwLogonProvider As Integer, _
ByRef phToken As IntPtr) As Integer
Private Declare Function DuplicateToken Lib "advapi32.dll" ( _
ByVal ExistingTokenHandle As IntPtr, _
ByVal ImpersonationLevel As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Integer
Private Declare Function RevertToSelf Lib "advapi32.dll" () As Integer
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function GetShortPathName(ByVal longPath As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal ShortPath As StringBuilder, <MarshalAs(UnmanagedType.U4)> ByVal bufferSize As Integer) As Integer
End Function
Public Const FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000
<DllImport("Kernel32.dll")> _
Public Shared Function FormatMessage(ByVal flags As Integer, ByVal [source] As IntPtr, ByVal messageId As Integer, ByVal languageId As Integer, ByVal buffer As StringBuilder, ByVal size As Integer, ByVal arguments As IntPtr) As Integer
End Function
#End Region
#Region "Shared Properties"
Public Shared ReadOnly Property CurrentlyLoggedOnUser() As String
Get
If IsImpersonating Then
Return _windowsIdentity.Name
Else
Return System.Threading.Thread.CurrentPrincipal.Identity.Name
End If
End Get
End Property
Private Shared _isImpersonating As Boolean = False
Public Shared ReadOnly Property IsImpersonating() As Boolean
Get
Return _isImpersonating
End Get
End Property
#End Region
#Region "Shared Methods"
Public Shared Function impersonateValidUser(ByVal userName As String, _
ByVal domain As String, ByVal password As String) As Boolean
Dim token As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
Dim returnValue As Boolean = False
If RevertToSelf() <> 0 Then
If LogonUserA(userName, domain, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
_windowsIdentity = New WindowsIdentity(tokenDuplicate)
_impersonationContext = _windowsIdentity.Impersonate()
If Not _impersonationContext Is Nothing Then
returnValue = True
_isImpersonating = True
System.Threading.Thread.CurrentPrincipal = New System.Security.Principal.WindowsPrincipal(_windowsIdentity) '_impersonationContext
Else
returnValue = False
_isImpersonating = False
My.User.InitializeWithWindowsUser()
End If
End If
Else
'there was an error
returnValue = False
_isImpersonating = False
Dim errorNumber As Integer = Marshal.GetLastWin32Error()
If errorNumber = 1326 Then
Throw New Exception("Windows DomainAccount Authentication Failed ")
Else
Dim sbFormatMessage As New StringBuilder(1024)
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, errorNumber, 0, sbFormatMessage, sbFormatMessage.Capacity, IntPtr.Zero)
Throw New Exception("Error occured. GetLastError returns " & System.Runtime.InteropServices.Marshal.GetLastWin32Error.ToString & System.Environment.NewLine & _
sbFormatMessage.ToString())
End If
returnValue = False
_isImpersonating = False
My.User.InitializeWithWindowsUser()
End If
End If
If Not tokenDuplicate.Equals(IntPtr.Zero) Then
CloseHandle(tokenDuplicate)
End If
If Not token.Equals(IntPtr.Zero) Then
CloseHandle(token)
End If
Return returnValue
End Function
Public Shared Sub undoImpersonation()
If _impersonationContext IsNot Nothing Then
_impersonationContext.Undo()
_impersonationContext = Nothing
_isImpersonating = False
My.User.InitializeWithWindowsUser()
End If
End Sub
#End Region
End Class
【讨论】:
谢谢。我试试看。 我用这段代码构建了一个 VB.NET 解决方案。我得到与上面完全相同的错误。 我解决了这个问题。我在 GetAccessControl 中使用 X:filename。使用实际的服务器路径修复它。猜猜没有关于模拟的映射。 @David,我很好奇。请你解释一下 X:filename 是什么意思? X:是一个映射驱动器吗?此外,如果您发布自己问题的答案,您可以自己接受,其他人可能会从您的发现中受益。【参考方案2】:我解决了这个问题。我在 GetAccessControl 中使用 X:filename。使用实际的服务器路径修复它。猜猜没有模拟上的映射
【讨论】:
以上是关于进行模拟后无法获取访问控制,出现错误的主要内容,如果未能解决你的问题,请参考以下文章
SQL 访问控制错误:权限不足,无法对架构“INFORMATION_SCHEMA”进行操作
一天一坑系列无法访问Controller:SpringBoot项目启动后,请求无法进入控制器Controller中(可以进入服务,但是无法访问控制器)
由于访问控制检查,ios Safari XMLHttpRequest 无法加载
添加 Access-Control-Allow-Origin 后,仍然出现“请求的资源上没有“访问控制允许来源”标头”错误:*