Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 登录用户和授权_C#_Winapi_Impersonation_Delegation - Fatal编程技术网

C# 登录用户和授权

C# 登录用户和授权,c#,winapi,impersonation,delegation,C#,Winapi,Impersonation,Delegation,我正在使用LogonUser win32 api: token = LogonUser(...) WindowsIdentity newId = new WindowsIdentity(token); WindowsImpersonationContext impersonatedUser = newId.Impersonate(); 但是,在此之后调用WCF服务时,我无法使用模拟身份。我认为这是因为impersonatedUser.ImpersonationLevel

我正在使用LogonUser win32 api:

token = LogonUser(...)
WindowsIdentity newId = new WindowsIdentity(token);            
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
但是,在此之后调用WCF服务时,我无法使用模拟身份。我认为这是因为impersonatedUser.ImpersonationLevel等于模拟

这是原因吗? 是一个模拟级别。我需要什么身份?
如何达到这样的水平?

我不知道这是否适用于WCF。但我们在我们的生产web应用程序中使用它来模拟文件系统的读写操作。您需要为AdvApi32.LogonUser、AdvApi32.DuplicateToken和Kernel32.CloseHandle定义API,并确保完成后关闭WindowsImpersonationContext

    /// <summary>impersonates a user</summary>
    /// <param name="username">domain\name of the user account</param>
    /// <param name="password">the user's password</param>
    /// <returns>the new WindowsImpersonationContext</returns>
    public static WindowsImpersonationContext ImpersonateUser(String username, String password)
    {
        WindowsIdentity winId = WindowsIdentity.GetCurrent();
        if (winId != null)
        {
            if (string.Compare(winId.Name, username, true) == 0)
            {
                return null;
            }
        }

        //define the handles
        IntPtr existingTokenHandle = IntPtr.Zero;
        IntPtr duplicateTokenHandle = IntPtr.Zero;

        String domain;
        if (username.IndexOf("\\") > 0)
        {
            //split domain and name
            String[] splitUserName = username.Split('\\');
            domain = splitUserName[0];
            username = splitUserName[1];
        }
        else
        {
            domain = String.Empty;
        }

        try
        {
            //get a security token

            bool isOkay = AdvApi32.LogonUser(username, domain, password,
                (int) AdvApi32.LogonTypes.LOGON32_LOGON_INTERACTIVE,
                (int) AdvApi32.LogonTypes.LOGON32_PROVIDER_DEFAULT,
                ref existingTokenHandle);

            if (!isOkay)
            {
                int lastWin32Error = Marshal.GetLastWin32Error();
                int lastError = Kernel32.GetLastError();

                throw new Exception("LogonUser Failed: " + lastWin32Error + " - " + lastError);
            }

            // copy the token

            isOkay = AdvApi32.DuplicateToken(existingTokenHandle,
                (int) AdvApi32.SecurityImpersonationLevel.SecurityImpersonation,
                ref duplicateTokenHandle);

            if (!isOkay)
            {
                int lastWin32Error = Marshal.GetLastWin32Error();
                int lastError = Kernel32.GetLastError();
                Kernel32.CloseHandle(existingTokenHandle);
                throw new Exception("DuplicateToken Failed: " + lastWin32Error + " - " + lastError);
            }
            // create an identity from the token

            WindowsIdentity newId = new WindowsIdentity(duplicateTokenHandle);
            WindowsImpersonationContext impersonatedUser = newId.Impersonate();

            return impersonatedUser;
        }
        finally
        {
            //free all handles
            if (existingTokenHandle != IntPtr.Zero)
            {
                Kernel32.CloseHandle(existingTokenHandle);
            }
            if (duplicateTokenHandle != IntPtr.Zero)
            {
                Kernel32.CloseHandle(duplicateTokenHandle);
            }
        }
    }
///模拟用户
///域\用户帐户的名称
///用户的密码
///新的WindowsImpersonationContext
公共静态WindowsImpersonationContext ImpersonateUser(字符串用户名、字符串密码)
{
WindowsIdentity winId=WindowsIdentity.GetCurrent();
if(winId!=null)
{
if(string.Compare(winId.Name,username,true)==0)
{
返回null;
}
}
//定义句柄
IntPtr existingTokenHandle=IntPtr.Zero;
IntPtr duplicateTokenHandle=IntPtr.Zero;
字符串域;
if(username.IndexOf(“\\”)>0)
{
//拆分域名
字符串[]splitUserName=username.Split('\\');
domain=splitUserName[0];
用户名=拆分用户名[1];
}
其他的
{
domain=String.Empty;
}
尝试
{
//获取安全令牌
bool isOkay=AdvApi32.LogonUser(用户名、域、密码、,
(int)AdvApi32.LogonTypes.LOGON32\u LOGON\u INTERACTIVE,
(int)AdvApi32.LogonTypes.LOGON32\u提供程序\u默认值,
ref existingTokenHandle);
如果(!isOkay)
{
int lastWin32Error=Marshal.GetLastWin32Error();
int lastError=Kernel32.GetLastError();
抛出新异常(“LogonUser失败:+lastWin32Error+”-“+lastError”);
}
//复制令牌
isOkay=AdvApi32.DuplicateToken(现有TokenHandle,
(int)AdvApi32.SecurityImpersonationLevel.SecurityImpersonation,
ref(手柄);
如果(!isOkay)
{
int lastWin32Error=Marshal.GetLastWin32Error();
int lastError=Kernel32.GetLastError();
内核32.CloseHandle(existingTokenHandle);
抛出新异常(“DuplicateToken失败:“+lastWin32Error+”-“+lastError”);
}
//从令牌创建标识
WindowsIdentity newId=新WindowsIdentity(duplicateTokenHandle);
WindowsImpersonationContext impersonatedUser=newId.Impersonate();
返回模拟用户;
}
最后
{
//释放所有手柄
if(existingTokenHandle!=IntPtr.Zero)
{
内核32.CloseHandle(existingTokenHandle);
}
if(duplicateTokenHandle!=IntPtr.Zero)
{
内核32.CloseHandle(重复的TokenHandle);
}
}
}
在这之后,我不能使用 冒充身份

模拟应能有效访问同一个框,但不能访问网络

正如consultutah的代码所示,您可能只需要调用DuplicateToken(),以便在使用登录令牌之前将其转换为模拟令牌

我认为这是因为impersonatedUser.ImpersonationLevel等于模拟


如果您需要充当其他系统的模拟用户,则需要更高级别的模拟,称为“委派”。这基本上相当于拥有用户的密码,这样您就可以向其他人表示您自己。

请注意那些有兴趣创建WindowsIdentity实例的人:
WindowsIdentity.Dispose()
关闭其令牌句柄,这意味着您不需要调用
CloseHandle(duplicateTokenHandle)
如果你打电话给
Dispose
@Joh-我认为这不对
Dispose
确实调用了
CloseHandle()
,但不调用传递给构造函数的句柄。构造函数复制提供的句柄;它是在
Dispose
中关闭的副本。