登录用户和委托

发布于 2024-07-24 04:21:09 字数 396 浏览 2 评论 0原文

我正在使用 LogonUser win32 api:

token = LogonUser(...)
WindowsIdentity newId = new WindowsIdentity(token);            
WindowsImpersonationContext impersonatedUser = newId.Impersonate();

但是,在此之后调用 WCF 服务时,我无法使用模拟身份。 我认为这是因为 impersonatedUser.ImpersonationLevel 等于 Impersonation。

是这个原因吗? 我需要 ImpersonationLevel.Identification 级别吗? 怎样才能达到这样的水平呢?

I'm using the LogonUser win32 api:

token = LogonUser(...)
WindowsIdentity newId = new WindowsIdentity(token);            
WindowsImpersonationContext impersonatedUser = newId.Impersonate();

However when calling a WCF service after this I'm not able to use the impersonated identity. I think this is because impersonatedUser.ImpersonationLevel equals Impersonation.

Is this the reason?
Is a level of ImpersonationLevel.Identification what I need?
How to get such a level?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

春夜浅 2024-07-31 04:21:09

我不知道这是否适用于 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);
            }
        }
    }

I don't know if this will work for WCF. But we use it in our production web app for impersonation to read and write files to the file system. You will need to define the API's for AdvApi32.LogonUser, AdvApi32.DuplicateToken, and Kernel32.CloseHandle and make sure to Close the WindowsImpersonationContext when you are done.

    /// <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);
            }
        }
    }
☆獨立☆ 2024-07-31 04:21:09

此后我无法使用
冒充身份

模拟应该对同一机器上的访问有效,但对网络上的访问无效。

正如 Consultutah 的代码所示,您可能只需要调用 DuplicateToken() 即可将登录令牌转换为模拟令牌,然后才能使用它。

我认为这是因为 impersonatedUser.ImpersonationLevel 等于 Impersonation。

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

after this I'm not able to use the
impersonated identity

The impersonation should be effective for access on the same box, but not on the network.

It may be, as consultutah's code shows, that you just need to call DuplicateToken() in order to convert the logon token to an impersonation token before it can be used.

I think this is because impersonatedUser.ImpersonationLevel equals Impersonation.

If you need to act as the impersonated user to other systems, you need a higher level of impersonation called 'delegation'. This is basically equivalent to having the user's password so you can represent yourself as them to others.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文