我们在应用程序中使用NTLM auth来确定用户是否可以执行某些操作。我们使用当前Windows登录的IPrincipal(在WinForms应用程序中),调用IsInRole来检查特定的组成员身份。
要检查用户是否是本机的本地管理员,我们使用:
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
...
bool allowed = Thread.CurrentPrincipal.IsInRole(@"Builtin\Administrators")
如果当前用户是Administrator
用户,或者是Builtin\Administrators
组成员的其他用户,则此方法有效。
在我们对Windows 7的测试中,我们发现它不再按预期工作。 Administrator
用户仍然可以正常使用,但Builtin\Administrators
组成员的任何其他用户都会因IsInRole
来电而返回false。
可能导致这种差异的原因是什么?我有一种直觉,认为默认设置在某处发生了变化(可能在gpedit中),但找不到任何看起来像罪魁祸首的东西。
答案 0 :(得分:9)
问题在于Windows安全(又名“UAC”)正在妨碍您。对管理员角色有特殊处理,在升级之前,您的用户实际上不会拥有这些角色。管理员角色在某种意义上是“幻影”:存在但不可用于权限检查甚至(轻松)测试存在。请参阅以下注释: http://msdn.microsoft.com/en-us/library/46ks97y7.aspx
以下是一个讨论该问题的系列文章,示例代码执行必要的解决方法:
我通过构建自己的UAC提示并使用名称&来解决ASP.NET应用程序中的类似问题。用于调用Win32 Logon API的密码。您可能很幸运能够使用.NET桌面应用程序,在这种情况下,您可以使用常规提升请求。
这里有一些C#代码可以在不提升的情况下检查管理员权限。
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;
}
它改编自我在网上找到的一篇文章,抱歉,丢失了归属信息。
答案 1 :(得分:7)
这对我有用 - 我需要的只是检查程序是否以管理员角色启动:
public static bool IsAdminRole()
{
AppDomain domain = Thread.GetDomain();
domain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal principle = (WindowsPrincipal)Thread.CurrentPrincipal;
return principle.IsInRole(WindowsBuiltInRole.Administrator);
}
希望有人发现使用它!
麦克
答案 2 :(得分:3)
我在stackoverflow上找到了另一篇文章,它解决了另一种方式。 我把它改编成下面的方法。 使用Windows 7时,对于管理员,这返回true,对于非管理员,则返回false,对于以管理员身份运行时,对于非管理员,则返回true。 看起来这只适用于.Net 3.5和XP SP2及更高版本,基于最初的MSDN for PrincipleContext类。
private static bool IsUserAdmin()
{
bool isAdmin = false;
WindowsIdentity wi = WindowsIdentity.GetCurrent();
WindowsPrincipal wp = new WindowsPrincipal(wi);
isAdmin = wp.IsInRole(WindowsBuiltInRole.Administrator);
Console.WriteLine(isAdmin); // False for Windows 7 even if user is admin
//found the code below at [http://stackoverflow.com/questions/1089046/in-net-c-test-if-user-is-an-administrative-user][1]
// Add reference to System.DirectoryServices.AccountManagement (Add Referemce -> .Net)
// Add using System.DirectoryServices.AccountManagement;
if (!isAdmin) //PrincipleContext takes a couple seconds, so I don't use it if not necessary
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Machine, null))
{
UserPrincipal up = UserPrincipal.Current;
GroupPrincipal gp = GroupPrincipal.FindByIdentity(pc, "Administrators");
if (up.IsMemberOf(gp))
{
isAdmin = true;
}
}
}
Console.WriteLine(isAdmin); // True for Windows 7 if user is admin
return isAdmin;
}
答案 3 :(得分:1)
您的申请没有提升。在正常情况下,UAC剥离了用户的“管理员”。如果应用程序只能由管理员使用,请添加一个使其升级的清单,以便他们可以保持管理。如果它可以被任何一个使用,你最好的选择是分成两部分,一部分带有提升清单而另一部分没有,并从一个用盾牌装饰的按钮或菜单项启动提升部分,这样用户就不会点击如果他们不是管理员。 (在较旧的操作系统上,将屏蔽按钮的消息将被忽略。)搜索“UAC”,“分区”和“shellexecute”将会很有帮助。
答案 4 :(得分:0)
我使用了与DavB.cs相同的方法:http://tieledeclercq.blogspot.be/2013/09/c-is-this-valid-administrator-that-can.html
有一些差异: