在Server服务器上有一个目录(暂时叫Server文件夹吧),在该文件夹上做了权限设置,设置只有Kevin和Tom两个用户有权限对这个文件夹进行操作(上传文件),现在新来了个员工Joms,这个人暂时也需要有对该文件夹上传文件的权限,但是又不想直接给他设置权限,希望能够让他模拟Kevin或者Tom的权限来操作
想了好久,后来公司的老员工想到了这个方法:
现在把代码贴出来大家看看,如果有什么好的方法记的PM我哦!!!
UpdateFile
{
private string tempPath = string.Empty; // 构造函数
public UpdateFile() { this.tempPath = Environment.GetEnvironmentVariable("WINDIR");
//处理文件夹路径 if (!this.tempPath.Substring(this.tempPath.Length - 1).Equals(@"\")) { this.tempPath = this.tempPath + @"\"; } this.tempPath = this.tempPath + @"TEMP\"; }
//调用非托管代码CloseHandle用于关闭句柄 [DllImport("kernel32.dll", CharSet=CharSet.Auto)] private static extern bool CloseHandle(IntPtr handle);
//上传文件方法 public bool UpFile(string fileFrom, string fileTo) { return this.UpFile(fileFrom, fileTo, string.Empty, string.Empty, string.Empty); } public bool UpFile(string fileFrom, string fileTo, string domainName, string userName, string userPassword) { IntPtr phToken = new IntPtr(0); IntPtr duplicateTokenHandle = new IntPtr(0); bool flag = false; try {
//判断提供的米你登入的帐号,密码为空
if ((userName.Equals(string.Empty) || userPassword.Equals(string.Empty)) || (domainName.Equals(string.Empty) || WindowsIdentity.GetCurrent().Name.ToLower().Equals(userName.ToLower().Trim()))) { File.Copy(fileFrom, fileTo, true); return flag; }
//定义句柄 phToken = IntPtr.Zero; duplicateTokenHandle = IntPtr.Zero;
//LogonUser也是一个非托管代码集中的方法,这中间的phToken就是用帐号登入后的模拟句柄 flag = LogonUser(userName, domainName, userPassword, 2, 0, ref phToken); if (!flag) { return flag; }
//进一步 if (!DuplicateToken(phToken, 2, ref duplicateTokenHandle)) {
//关闭句柄 CloseHandle(phToken); return false; }
//WindowImpersonationContext类是一个用于模拟操作之前的 Windows 用户也就是DuplicateToken用户。 WindowsImpersonationContext context = new WindowsIdentity(duplicateTokenHandle).Impersonate(); File.Copy(fileFrom, fileTo, true);
//完成上传后撤消帐号的模拟登入,恢复为原始标识。 context.Undo(); if (phToken != IntPtr.Zero) { CloseHandle(phToken); } if (duplicateTokenHandle != IntPtr.Zero) { CloseHandle(duplicateTokenHandle); } flag = true; } catch (Exception exception) { throw exception; } return flag; } [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] private static extern bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); [DllImport("advapi32.dll", SetLastError=true)] private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); // Properties public string SystemTempPath { get { return this.tempPath; } }} 希望对大家有帮助!
新加一个测试程序,主要是验证调用了LogonUser和DuplicateToken方法前后,系统显示的"当前登入的用户名"的不同
using System;
using System.Runtime.InteropServices;
using System.Configuration;
using System.ComponentModel;
using System.Diagnostics;
using System.Security.Principal;
namespace DuplicationTokenLogin
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
IntPtr tokenHandle =new IntPtr(0);
IntPtr DupeHandle = new IntPtr(0);
string sDemainName = string.Empty;
string sUserName =string.Empty;
string sPwd =string.Empty;
Console.WriteLine("Welcome to the test Environment!");
Console.Write("Please input the name of Demain which you want to logon:");
sDemainName =Console.ReadLine();
Console.Write("Please input your Account which you used to logon the Demain of {0}:",sDemainName);
sUserName =Console.ReadLine();
Console.Write("Please input your Password used to logon:");
sPwd =Console.ReadLine();
tokenHandle =IntPtr.Zero;
DupeHandle =IntPtr.Zero;
//LogonUser的第四个参数传递2表示通过网络验证帐号,第五个参数传递0表示用默认的WindowNT来验证
bool bLogon = LogonUser(sUserName,sDemainName,sPwd,2,0,ref tokenHandle);
if(!bLogon)
{
Console.WriteLine("When logon have error!");
return;
}
Console.WriteLine("Did LogonUser Succeed:" + (bLogon?"Yes":"No"));
Console.WriteLine("-----------------------------------------------------------");
Console.WriteLine("value of WindowNT token is {0}",tokenHandle);
Console.WriteLine("Before impersonation the user,the Logon UserName is{0}",WindowsIdentity.GetCurrent().Name);
bool bImpersonation = DuplicateToken(tokenHandle,2,ref DupeHandle);
if(!bImpersonation)
{
Console.WriteLine("模拟用户的时候出现错误!");
return;
}
WindowsImpersonationContext context = new WindowsIdentity(DupeHandle).Impersonate();
Console.WriteLine("Did ImpersonationUser Secceed:" + (bImpersonation?"Yes":"No"));
Console.WriteLine("----------------------------------------------------------");
Console.WriteLine("After ImpersonationUser,the Logon UserName is {0}",WindowsIdentity.GetCurrent().Name);
context.Undo();
Console.WriteLine("---------------------------------------------------------");
Console.WriteLine("After Undo,the UserName is {0}",WindowsIdentity.GetCurrent().Name);
if(tokenHandle !=IntPtr.Zero)
{
CloseHandle(tokenHandle);
}
if(DupeHandle !=IntPtr.Zero)
{
CloseHandle(DupeHandle);
}
Console.WriteLine("the Test is Seccued,and press the key of Enter to end the Test!");
Console.ReadLine();
}
[DllImport("advapi32.dll",SetLastError=true)]
private static extern bool LogonUser(string lpszUserName,string lpszDemain,string lpszPassword,int dwLogonType,int dwLogonProvider,ref IntPtr phToken);
[DllImport("advapi32.dll",CharSet =CharSet.Auto,SetLastError=true)]
private static extern bool DuplicateToken(IntPtr ExistingTokenHandle,int SECURITY_IMPERSONATION_LEVEL,ref IntPtr DuplicatonTokenHandle);
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);