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

一早在浏览代码时看到如下代码(我想这段代码的来源是kb306158),这段代码的作用是,当一个通过Active Directory账号登陆系统的用户,需要上传、创建目录、下载时,需要先校验该用户是否具有目录操作权限, 代码如下:

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登陆用户的校验大致有了一点了解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
安装 Hive 需要先安装 Hadoop,因为 Hive 需要依赖于 Hadoop 文件系统和 MapReduce。下面是基于 Hadoop 2.x 版本的 Hive 安装步骤: 1. 下载 Hive 安装包并解压缩到指定目录: ``` tar -zxf apache-hive-x.x.x-bin.tar.gz sudo mv apache-hive-x.x.x-bin /usr/local/hive ``` 2. 配置环境变量: ``` export HIVE_HOME=/usr/local/hive export PATH=$PATH:$HIVE_HOME/bin ``` 3. 修改 Hive 配置文件 hive-site.xml: ``` cd $HIVE_HOME/conf cp hive-default.xml.template hive-site.xml vi hive-site.xml ``` 在 hive-site.xml 文件中添加以下配置信息: ``` <configuration> <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true</value> <description>JDBC connect string for a JDBC metastore</description> </property> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.jdbc.Driver</value> <description>Driver class name for a JDBC metastore</description> </property> <property> <name>javax.jdo.option.ConnectionUserName</name> <value>hive</value> <description>Username to use against metastore database</description> </property> <property> <name>javax.jdo.option.ConnectionPassword</name> <value>hive</value> <description>Password to use against metastore database</description> </property> <property> <name>hive.metastore.warehouse.dir</name> <value>/user/hive/warehouse</value> <description>Location of Hive warehouse directory</description> </property> <property> <name>hive.exec.local.scratchdir</name> <value>/tmp/hive</value> <description>Local scratch space for Hive jobs</description> </property> <property> <name>hive.querylog.location</name> <value>/var/log/hive</value> <description>Location of Hive query log</description> </property> <property> <name>hive.server2.enable.doAs</name> <value>false</value> <description>Enable impersonation for HiveServer2</description> </property> <property> <name>hive.server2.thrift.port</name> <value>10000</value> <description>TCP port number for HiveServer2</description> </property> </configuration> ``` 4. 修改 Hive 配置文件 hive-env.sh: ``` cd $HIVE_HOME/conf cp hive-env.sh.template hive-env.sh vi hive-env.sh ``` 在 hive-env.sh 文件中添加以下配置信息: ``` export HADOOP_HOME=/usr/local/hadoop export HIVE_CONF_DIR=/usr/local/hive/conf export HIVE_AUX_JARS_PATH=$HADOOP_HOME/share/hadoop/common/lib/mysql-connector-java-x.x.x.jar ``` 5. 启动 Hive 元数据存储服务: ``` schematool -initSchema -dbType mysql ``` 6. 启动 Hive 服务: ``` hive --service metastore & hive --service hiveserver2 & ``` 至此,Hive 部署完成。可以通过 `hive -e "show databases;"` 测试 Hive 是否正常运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值