在Windows调用IPrincipal.IsInRole 7Windows、IPrincipal、IsInRole

由网友(辣條五毛壹包)分享简介:我们使用NTLM身份验证在我们的应用程序,以确定用户是否可以执行某些操作。我们使用IPrincipal他们当前的Windows登录(在的WinForms应用程序),称IsInRole检查特定的组成员。We use NTLM auth in our application to determine whether a...

我们使用NTLM身份验证在我们的应用程序,以确定用户是否可以执行某些操作。我们使用IPrincipal他们当前的Windows登录(在的WinForms应用程序),称IsInRole检查特定的组成员。

We use NTLM auth in our application to determine whether a user can perform certain operations. We use the IPrincipal of their current Windows login (in WinForms applications), calling IsInRole to check for specific group memberships.

要检查用户的计算机上的本地管理员,我们使用:

To check that a user is a local administrator on the machine, we use:

AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
...
bool allowed = Thread.CurrentPrincipal.IsInRole(@"BuiltinAdministrators")

这工作,如果当前用户是管理​​的用户,或者是其他用户是这样的内建 Administrators组的成员组。

This works if the current user is the Administrator user, or is another user that is a member of the BuiltinAdministrators group.

在我们的测试在Windows 7中,我们已经发现,这不再按预期工作。该管理​​用户仍然能正常工作,但任何其他用户也就是内建管理员组的成员返回false在 IsInRole 电话。

In our testing on Windows 7, we have found that this no longer works as expected. The Administrator user still works fine, but any other user that is a member of the BuiltinAdministrators group returns false for the IsInRole call.

这可能是造成这种差异?我有一个直觉的默认设置已经改变的地方(可能在gpedit),但无法找到任何看起来像罪魁祸首。

What could be causing this difference? I have a gut feeling that a default setting has changed somewhere (possible in gpedit), but cannot find anything that looks like the culprit.

推荐答案

问题是,Windows安全(又名UAC)是在你的方式。有管理员角色的特殊处理,你的用户将不能真正拥有这些角色,直到他被提升。在某种意义上管理员角色幻像:present但对于权限检查,甚至到(容易)测试presence不可用。见注,: http://msdn.microsoft.com/en-us/library/46ks97y7.aspx

The problem is that Windows security (aka "UAC") is getting in your way. There's special handling of administrator roles and your user will not actually have these roles until he is elevated. Admin roles are "ghosted" in a sense: present but unavailable for permission checks or even to (easily) test for presence. See the note at: http://msdn.microsoft.com/en-us/library/46ks97y7.aspx

下面是一个系列谈这个问题,有例如code,做必要的解决方法:

Here's a series that talks about the issue, with example code that does the necessary workarounds:

http://www.simple-talk.com/community/blogs/dana/archive/2008/03/17/45354.aspx http://www.simple-talk.com/community/blogs/dana/archive/2008/03/17/45352.aspx http://www.simple-talk.com/community/blogs/dana/archive/2008/03/17/45354.aspx http://www.simple-talk.com/community/blogs/dana/archive/2008/03/17/45352.aspx

我解决了一个ASP.NET应用程序类似的问题,通过建设自己的UAC提示,并使用名称和放大器;密码调用Win32 API登录。你可能会幸运地成为在.NET桌面应用程序,在这种情况下,你可以使用普通的提升请求。

I solved a similar problem in an ASP.NET app by building my own UAC prompt and using the name & password to call the Win32 Logon API. You might be lucky enough to be in a .NET desktop app, in which case you can use regular elevation requests.

下面是一些C#code检查管理权限,而不提升。

Here's some C# code to check admin permissions without elevating.

    public const UInt32 TOKEN_DUPLICATE = 0x0002;
    public const UInt32 TOKEN_IMPERSONATE = 0x0004;
    public const UInt32 TOKEN_QUERY = 0x0008;

    public enum TOKEN_ELEVATION_TYPE
    {
        TokenElevationTypeDefault = 1,
        TokenElevationTypeFull,
        TokenElevationTypeLimited
    }

    public enum TOKEN_INFORMATION_CLASS
    {
        TokenUser = 1,
        TokenGroups,
        TokenPrivileges,
        TokenOwner,
        TokenPrimaryGroup,
        TokenDefaultDacl,
        TokenSource,
        TokenType,
        TokenImpersonationLevel,
        TokenStatistics,
        TokenRestrictedSids,
        TokenSessionId,
        TokenGroupsAndPrivileges,
        TokenSessionReference,
        TokenSandBoxInert,
        TokenAuditPolicy,
        TokenOrigin,
        TokenElevationType,
        TokenLinkedToken,
        TokenElevation,
        TokenHasRestrictions,
        TokenAccessInformation,
        TokenVirtualizationAllowed,
        TokenVirtualizationEnabled,
        TokenIntegrityLevel,
        TokenUIAccess,
        TokenMandatoryPolicy,
        TokenLogonSid,
        MaxTokenInfoClass  // MaxTokenInfoClass should always be the last enum 
    }

    public enum SECURITY_IMPERSONATION_LEVEL
    {
        SecurityAnonymous,
        SecurityIdentification,
        SecurityImpersonation,
        SecurityDelegation
    }


    public static bool IsAdmin()
    {
        var identity = WindowsIdentity.GetCurrent();
        return (null != identity && new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator));
    }

    /// <summary>
    /// The function checks whether the primary access token of the process belongs
    /// to user account that is a member of the local Administrators group, even if
    /// it currently is not elevated.
    /// </summary>
    /// <returns>
    /// Returns true if the primary access token of the process belongs to user
    /// account that is a member of the local Administrators group. Returns false
    /// if the token does not.
    /// </returns>
    public static bool CanBeAdmin()
    {
        bool fInAdminGroup = false;
        IntPtr hToken = IntPtr.Zero;
        IntPtr hTokenToCheck = IntPtr.Zero;
        IntPtr pElevationType = IntPtr.Zero;
        IntPtr pLinkedToken = IntPtr.Zero;
        int cbSize = 0;

        if (IsAdmin())
            return true;

        try
        {
            // Check the token for this user
            hToken = WindowsIdentity.GetCurrent().Token;

            // Determine whether system is running Windows Vista or later operating
            // systems (major version >= 6) because they support linked tokens, but
            // previous versions (major version < 6) do not.
            if (Environment.OSVersion.Version.Major >= 6)
            {
                // Running Windows Vista or later (major version >= 6).
                // Determine token type: limited, elevated, or default.

                // Allocate a buffer for the elevation type information.
                cbSize = sizeof(TOKEN_ELEVATION_TYPE);
                pElevationType = Marshal.AllocHGlobal(cbSize);
                if (pElevationType == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                // Retrieve token elevation type information.
                if (!GetTokenInformation(hToken,
                    TOKEN_INFORMATION_CLASS.TokenElevationType, pElevationType, cbSize, out cbSize))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                // Marshal the TOKEN_ELEVATION_TYPE enum from native to .NET.
                TOKEN_ELEVATION_TYPE elevType = (TOKEN_ELEVATION_TYPE)Marshal.ReadInt32(pElevationType);

                // If limited, get the linked elevated token for further check.
                if (elevType == TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited)
                {
                    // Allocate a buffer for the linked token.
                    cbSize = IntPtr.Size;
                    pLinkedToken = Marshal.AllocHGlobal(cbSize);
                    if (pLinkedToken == IntPtr.Zero)
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }

                    // Get the linked token.
                    if (!GetTokenInformation(hToken,
                        TOKEN_INFORMATION_CLASS.TokenLinkedToken, pLinkedToken,
                        cbSize, out cbSize))
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }

                    // Marshal the linked token value from native to .NET.
                    hTokenToCheck = Marshal.ReadIntPtr(pLinkedToken);
                }
            }

            // CheckTokenMembership requires an impersonation token. If we just got
            // a linked token, it already is an impersonation token.  If we did not
            // get a linked token, duplicate the original into an impersonation
            // token for CheckTokenMembership.
            if (hTokenToCheck == IntPtr.Zero)
            {
                if (!DuplicateToken(hToken, (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, ref hTokenToCheck))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }

            // Check if the token to be checked contains admin SID.
            WindowsIdentity id = new WindowsIdentity(hTokenToCheck);
            WindowsPrincipal principal = new WindowsPrincipal(id);
            fInAdminGroup = principal.IsInRole(WindowsBuiltInRole.Administrator);
        }
        catch
        {
            return false;
        }
        finally
        {
            // Centralized cleanup for all allocated resources.
            if (pElevationType != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(pElevationType);
                pElevationType = IntPtr.Zero;
            }
            if (pLinkedToken != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(pLinkedToken);
                pLinkedToken = IntPtr.Zero;
            }
        }

        return fInAdminGroup;
    }

它是改编自一篇文章,我在网上找到的地方,对不起,失去了归属。

It's adapted from an article I found online somewhere, sorry, lost the attribution.

阅读全文

相关推荐

最新文章