文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>使用C# impersonation进行windows帐号的校验

使用C# impersonation进行windows帐号的校验

时间:2011-03-06  来源:Newbie Elaine

public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
private string _logOnUsername;
private string _logOnDomain;
private string _logOnPassword;

WindowsImpersonationContext impersonationContext;

// to check whether the acct info input is a logoned one, 
// if past the validation, output a token 
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int LogonUser(String lpszUserName,
    String lpszDomain,
    String lpszPassword,
    int dwLogonType,
    int dwLogonProvider,
    ref IntPtr phToken);

// create a new token derived from the input token
[DllImport("advapi32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto,
        SetLastError = true)]
public extern static int DuplicateToken(IntPtr hToken,
    int impersonationLevel,
    ref IntPtr hNewToken);

// to impersonate
private bool impersonateValidUser(String userName, String domain, String password)
{
    WindowsIdentity tempWindowsIdentity;
    IntPtr token = IntPtr.Zero;
    IntPtr tokenDuplicate = IntPtr.Zero;

    // validate whether logoned on with the supplied parameters
    if (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
        LOGON32_PROVIDER_DEFAULT, ref token) != 0)
    {
         // SecurityImpersonation
         // The server can impersonate the client's security context on the local system.
         if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
        {
            tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
            impersonationContext = tempWindowsIdentity.Impersonate();
            if (impersonationContext != null)
                return true;
            else
                return false;
        }
        else
            return false;
    }
    else
        return false;
}

private void undoImpersonation()
{
    impersonationContext.Undo();
}

// the parameters' value are all kept in web.config,
// it's a fixed account, not current logined user's acct.
public FileAccess(string logonDomain, string logonUsername, string logonPassword)
{
    _logOnDomain = logonDomain;
    _logOnUsername = logonUsername;
    _logOnPassword = logonPassword;
}

public bool FileExists(string filePathName)
{
    if (impersonateValidUser(_logOnUsername, _logOnDomain, _logOnPassword))
    {
        try
        {
            if (File.Exists(filePathName))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        finally
        {
            undoImpersonation();
        }
    }
    else
    {
        throw (new Exception("Failed in impersonation."));
    }
}


代码中使用FileAccess进行对象初始化,其中logonDomain,logonUserName,logonPWD均被配置于web.config中。使用impersonateValidUser方法校验目录操作权限,

Q: 为什么需要DuplicateToken

A: 先要了解进行Windows校验所需要的一点基础,文中认为使用LogonUser后拿到的token是当前用户的,我们不能用它来创建对象或是做别的什么事,这样不安全,所以应该使用如下两种中的一种来创建被复制的新token,

> SecurityImpersonation    The server can impersonate the client's security context on the local system.

> SecurityDelegation    The server can impersonate the client's security context on remote systems.

At the SecurityImpersonation level, most of the thread's actions occur in the security context of the thread's impersonation token rather than in the primary token of the process that owns the thread. For example, if an impersonating thread opens a securable object, the system uses the impersonation token to check the thread's access. Similarly, if an impersonating thread creates a new object, for example by calling the CreateFile function, the owner of the new object is the default owner from the client's access token.

Q: 这个被模拟的用户(即此处的FileAccess中传入的帐号信息)的权限应该设置为什么?

A: 在KB306158中,已经给出如下解决方案

> 为 ASPNET 帐户授予“作为操作系统的一部分”权限。(注意:我们不建议使用这种方法解决此问题。)

> 在 Machine.config 文件的 <processModel> 配置节中,将运行 Aspnet_wp.exe 进程所使用的帐户更改为 System 帐户。

在此贴中,这位大牛提出了这个问题,他认为无论是使用LogonUser还是使用System.DiretoryServices都是不完美的,有漏洞的。比如LogonUser必须会提供一个有SE_CHANGE_NOTIFY_NAME权限的账号,这个比较麻烦,使用DirectoryServices则需要查看AD属性,并认为这种方式会在客户端留下AD scheme的缓存,代价太大不划算,且GetLastError捕捉的异常也并不能100%定位是否是用户校验未通过,见下面这段代码。

// create a "principal context" - e.g. your domain (could be machine, too)
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YOURDOMAIN"))
{
    // validate the credentials
    bool isValid = pc.ValidateCredentials("myuser", "mypassword")
}

还可以进行一些延伸阅读 See also:

  1. Create a Web Service Method to Manage a NT Service
  2. 微软KB306158:How to implement impersonation in an ASP.NET application (可自行将en-us改成zh-cn转向中文版)
  3. 关于etern关键字和DLLImport
  4. DuplicateToken Function
  5. WindowsIdentity
  6. impersonationContext.Undo()
  7. WindowsIdentity.Impersonate Method ()

我觉得到了这一步,我已经对windows/AD登陆用户的校验大致有了一点了解。

相关阅读 更多 +
排行榜 更多 +
找茬脑洞的世界安卓版

找茬脑洞的世界安卓版

休闲益智 下载
滑板英雄跑酷2手游

滑板英雄跑酷2手游

休闲益智 下载
披萨对对看下载

披萨对对看下载

休闲益智 下载