【问题标题】:How to get WindowsPrincipal from username and password如何从用户名和密码中获取 WindowsPrincipal
【发布时间】:2015-01-09 00:57:29
【问题描述】:

我正在使用 WebAPI 并使用 Katana 托管它。我现在正在编写一些用于身份验证和授权的中间件。我必须对 SSL 使用基本身份验证,因为请求可能来自各种平台。 OAuth 目前也不是一个选项。中间件需要获取基本身份验证提供的用户名和密码,并验证用户是本地 Windows 组的成员。

现在我正试图弄清楚如何创建一个 WindowsPrincipal。如果我能弄清楚如何从用户名和密码创建一个 WindowsPrincipal,我就知道如何去做剩下的事情了。这是我现在拥有的。

    //TODO
    WindowsPrincipal userPrincipal = null; //This is where I need to take the username and password and create a WindowsPrincipal
    Thread.CurrentPrincipal = userPrincipal;

    AppDomain.CurrentDomain.SetPrincipalPolicy(System.Security.Principal.PrincipalPolicy.WindowsPrincipal);
    PrincipalPermission permission = new PrincipalPermission(null, "Local Group Name");
    permission.Demand();

我正在努力寻找一种使用用户名和密码来验证该成员是否属于特定组的好方法。做这个的最好方式是什么?提前感谢您的帮助。

【问题讨论】:

    标签: c# basic-authentication


    【解决方案1】:

    实际上,我认为您应该使用 WindowsIdentity 而不是 WindowsPrincipal 来获取该信息。

    要获取/模拟用户,您必须从 advapi32.dll 中 p/调用 LogonUser():

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LogonUser(
            string lpszUsername,
            string lpszDomain,
            string lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            out IntPtr phToken);
    

    考虑到以上内容属于“Native”类,冒充用户如下:

    var userToken = IntPtr.Zero;
    
    var success = Native.LogonUser(
      "username", 
      "domain", 
      "password", 
      2, // LOGON32_LOGON_INTERACTIVE
      0, // LOGON32_PROVIDER_DEFAULT
      out userToken);
    
    if (!success)
    {
      throw new SecurityException("User logon failed");
    }
    
    var identity = new WindowsIdentity(userToken);
    
    if(identity.Groups.Any(x => x.Value == "Group ID")) 
    {
        // seems to be in the group!
    } 
    

    您可以在此处找到有关本机调用的更多信息:http://msdn.microsoft.com/en-us/library/windows/desktop/aa378184%28v=vs.85%29.aspx

    【讨论】:

    • 顺便说一句,如果您仍然需要访问 WindowsPrincipal,您可以从 WindowsIdentity 中生成它:WindowsPrincipal principal = new WindowsPrincipal(identity);
    • 像魅力一样工作。感谢您的帮助!关于这种方法的最后一个问题。我没有太多从托管代码调用本机代码的经验,并且想确保我清理了所有非托管资源。看起来我应该在 kernel32.dll 中使用 CloseHandle() 完成后关闭 userToken 的句柄。还有什么我应该清理的与我丢失的本机调用相关的东西吗?
    • 实际上,一旦您不再需要用户令牌,您无需执行任何其他操作即可调用 CloseHandle()。我相信 WindowsIdentity 的生命周期与令牌的生命周期无关,但您可能想自己尝试一下!
    猜你喜欢
    • 1970-01-01
    • 2011-03-17
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多