有问题冒充管理员用户将.cer(证书文件)文件安装到LocalComputer ...安装当前用户工作费用。
我总是收到错误消息" Acces Denied"。
使用以下代码进行模拟:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Principal;
public class ImpersonatedUser : IDisposable
{
IntPtr userHandle;
WindowsImpersonationContext impersonationContext;
public ImpersonatedUser(string domain,string user, string password)
{
userHandle = IntPtr.Zero;
bool loggedOn = LogonUser(
user,
domain,
password,
LogonType.Interactive,
LogonProvider.Default,
out userHandle);
if (!loggedOn)
throw new Win32Exception(Marshal.GetLastWin32Error());
// Begin impersonating the user
impersonationContext = WindowsIdentity.Impersonate(userHandle);
}
public void Dispose()
{
if (userHandle != IntPtr.Zero)
{
CloseHandle(userHandle);
userHandle = IntPtr.Zero;
impersonationContext.Undo();
}
}
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
LogonType dwLogonType,
LogonProvider dwLogonProvider,
out IntPtr phToken
);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hHandle);
enum LogonType : int
{
Interactive = 2,
Network = 3,
Batch = 4,
Service = 5,
NetworkCleartext = 8,
NewCredentials = 9,
}
enum LogonProvider : int
{
Default = 0,
WINNT50 = 3,
}
这是证书安装方法:
private static void InstallCertificate(string cerFileName, StoreName storeName)
{
LoginInfo loginInfo = new LoginInfo();
X509Certificate2 certificate = new X509Certificate2(cerFileName);
X509Store store = new X509Store(storeName, StoreLocation.LocalMachine);
try
{
store.Open(OpenFlags.ReadWrite);
store.Add(certificate);
store.Close();
}
catch (Exception e)
{
string CertName = Path.GetFileName(cerFileName);
string source = e.Source.ToString();
string message = e.Message.ToString();
string messagetext = string.Format("Certificate installation \"{0}\" was not succsessfull Error: {1}", CertName, message);
StringBuilder messagestring = new StringBuilder();
messagestring.Append(source);
messagestring.Append(message);
MessageBox.Show(messagetext, "Install Certificate Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
这就是我在ImpersonatedUser中调用Method的方式。
using (new ImpersonatedUser(loginInfo.DomainName, loginInfo.UserName, loginInfo.Password))
{
MessageBox.Show(WindowsIdentity.GetCurrent().Name);
InstallCertificate(certpath, StoreName.TrustedPublisher);
}
答案 0 :(得分:0)
MS有一个很好的帮助页面,例如:http://msdn.microsoft.com/en-us/library/w070t6ka.aspx
您的代码之间的明显区别是您不在函数中包含[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
限定符。如果这是库的一部分,您也需要为整个库执行此操作。
我假设您登录的用户有权安装证书 - 请确保您的用户拥有这些权利。
答案 1 :(得分:0)
以下是我用于模拟服务帐户的代码,事实证明它可以正常运行:
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Security.Principal;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
using System.Security;
using System.Configuration;
namespace ImpersonationUtil
{
/// <summary>
/// Facilitates impersonation of a Windows User.
/// </summary>
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class Impersonation : IDisposable
{
public string Environment { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string DomainName { get; set; }
public enum LogonType
{
Interactive = 2,
Network = 3,
Batch = 4,
Service = 5,
Unlock = 7,
NetworkClearText = 8,
NewCredentials = 9
}
public enum LogonProvider
{
Default = 0,
WinNT35 = 1,
WinNT40 = 2,
WinNT50 = 3
}
/// <summary>
/// Windows Token.
/// </summary>
private readonly SafeTokenHandle _handle;
/// <summary>
/// The impersonated User.
/// </summary>
private WindowsImpersonationContext impersonatedUser;
public Impersonation()
{
}
/// <summary>
/// Initializes a new instance of the Impersonation class. Provides domain, user name, and password for impersonation.
/// </summary>
/// <param name="domainName">Domain name of the impersonated user.</param>
/// <param name="userName">Name of the impersonated user.</param>
/// <param name="password">Password of the impersonated user.</param>
/// <remarks>
/// Uses the unmanaged LogonUser function to get the user token for
/// the specified user, domain, and password.
/// </remarks>
public Impersonation(AccountCredentials credentials)
{
string[] splitName = WindowsIdentity.GetCurrent().Name.Split('\\');
string name = (splitName.Length > 0) ? splitName[0] : null;
LogonType logonType = LogonType.Interactive;
LogonProvider logonProvider = LogonProvider.Default;
if (name != credentials.Domain)
{
logonType = LogonType.NewCredentials;
logonProvider = LogonProvider.WinNT50;
}
// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser(
credentials.UserName,
credentials.Domain,
credentials.Password,
(int)logonType,
(int)logonProvider,
out this._handle);
if (false == returnValue)
{
// Something went wrong.
int ret = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(ret);
}
this.impersonatedUser = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
}
/// <summary>
/// Initializes a new instance of the Impersonation class. Provide domain, user name, and password for impersonation.
/// </summary>
/// <param name="domainName">Domain name of the impersonated user.</param>
/// <param name="userName">Name of the impersonated user.</param>
/// <param name="password">Password of the impersonated user.</param>
/// <remarks>
/// Uses the unmanaged LogonUser function to get the user token for
/// the specified user, domain, and password.
/// </remarks>
public Impersonation(string domainName, string userName, string password)
{
string[] splitName = WindowsIdentity.GetCurrent().Name.Split('\\');
string name = (splitName.Length > 0) ? splitName[0] : null;
LogonType logonType = LogonType.Interactive;
LogonProvider logonProvider = LogonProvider.Default;
if (name != domainName)
{
logonType = LogonType.NewCredentials;
logonProvider = LogonProvider.WinNT50;
}
// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser(
userName,
domainName,
password,
(int)logonType,
(int)logonProvider,
out this._handle);
if (false == returnValue)
{
// Something went wrong.
int ret = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(ret);
}
this.impersonatedUser = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
}
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
out SafeTokenHandle phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);
public void Dispose()
{
this.impersonatedUser.Dispose();
this._handle.Dispose();
}
private static string[] GetAccountInfo(string accountInfo)
{
return accountInfo.Split(' ');
}
}
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);
}
}
}
AccountCredentials.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security;
namespace ImpersonationUtil
{
public class AccountCredentials
{
public string UserName { get; set; }
public string Password { get; set; }
public string Domain { get; set; }
public AccountCredentials(string userName, string password, string domain)
{
UserName = userName;
Password = password;
Domain = domain;
}
}
}
使用示例:
AccountCredentials credentials = new AccountCredentials("user", "password", "domain");
using (new Impersonation(credentials))
{
// do work under the impersonated user
}
需要注意的重要一点是,在尝试模拟与活动域不在同一域中的帐户时,您必须使用正确的登录类型和登录提供程序。我检查了这一点,并在Impersonation构造函数中自动分配了正确的登录类型和登录提供程序。