我需要能够使用具有更高权限的acct来更改文件的访问权限。这是我的冒充代码:
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);
}
}
以下是使用模仿的片段:
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
答案 0 :(得分:0)
之前我已经完成了这个,但它在VB.net而不是C#,代码可能对你有所帮助,因为这肯定有用:
在Psuedo Code中,它是:
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
答案 1 :(得分:0)
我解决了这个问题。我在GetAccessControl中使用X:filename。使用实际的服务器路径修复它。猜猜没有模仿的映射