如何支持NTLM身份验证与ASP.NET MVC中的回退形式?

时间:2010-10-26 20:51:47

标签: c# asp.net-mvc authentication ntlm

如何在ASP.NET MVC应用程序中实现以下内容:

  1. 用户打开内联网网站
  2. 用户在可能的情况下进行无提示身份验证
  3. 如果NTLM身份验证没有成功,请向用户显示登录表单
  4. 用户指示登录密码并从预定义域列表中选择域
  5. 用户使用AD
  6. 在代码中进行身份验证

    我知道如何实现4和5,但无法找到有关如何组合NTLM和表单的信息。 因此,永远不会显示NTLM本机登录/密码对话框 - 透明身份验证或外观漂亮的登录页面。

    应该如何工作? 是否应该询问用户登录名和密码? 可以使用她当前的凭据(域用户名)而无需输入登录名和密码吗?

    更新这些问题,调查同样的问题:

    当我问这个时,我并不完全理解NTLM身份验证如何在内部工作。 这里需要了解的重要一点是,如果用户的浏览器不能正确支持NTLM,或者用户禁用了NTLM支持,那么服务器永远不会有机会解决这个问题。

    Windows身份验证的工作原理:

    1. 客户端向服务器发送常规HTTP请求
    2. 服务器以HTTP状态401响应并指示必须使用NTLM身份验证来访问资源
    3. 客户端发送NTLM Type1消息
    4. 服务器使用质询
    5. 响应NTLM Type2消息
    6. 客户端发送带有对质询的响应的Type3消息
    7. 服务器响应请求的实际内容
    8. 如您所见,不支持NTLM的浏览器不会转到步骤(3),而是会向用户显示IIS生成的错误401页面。

      如果用户没有凭据,取消NTLM身份验证后弹出对话框窗口浏览器也不会继续(3)。

      因此我们没有机会自动将用户重定向到自定义登录页面。

      这里唯一的选择是有一个“网关”页面,我们决定用户是否应该支持NTLM,如果是,请重定向到受NTLM保护的主页。

      如果没有,请显示登录表单并通过手动输入登录名和密码进行身份验证。

      通常通过匹配IP范围或检查预定义IP表来决定用户的IP地址和/或主机名。

3 个答案:

答案 0 :(得分:8)

这篇文章可能会让您指出正确的方向。基本上,在同一主机名下的两个虚拟目录中有两个应用程序。一个应用程序使用Forms身份验证,一个使用Windows。使用Windows身份验证的人会创建一个有效的表单身份验证cookie并重定向到第二个虚拟目录。

ASP.NET Mixed Mode Authentication

答案 1 :(得分:2)

我在生产中有这个确切的设置,我设置我的门户网站使用FormsAuth并编写了一个函数,让访问者IP查找登录到该IP / PC的用户帐户。使用我找到的名称(例如DOMAIN\user),我使用Membership.GetUser(<user>)验证域与我的域匹配,以及用户名/帐户在我的FormsAth提供程序中是否有效。如果此调用返回匹配项并且用户IsApproved我创建了FormsAuthenticationTicket&amp;用户的cookie。我在网络上有400多人,这完美无缺,唯一仍然登录的计算机是(1。我的门户网站没有帐户的用户,2。一些MAC / Linux用户,3。未在网络上启动的移动用户并使组策略启用其防火墙高。)

此解决方案的问题在于,它需要模拟域管理员帐户来查询用户PC,并且您使用非托管代码 netapi32.dll

这是我使用的代码(为简洁起见,未提供外部函数调用)。我试图简化这一点,因为有很多外部电话。

string account = String.Empty;
string domain = String.Empty;
string user = String.Empty;


ImpersonateUser iu = new ImpersonateUser();  //Helper that Enabled Impersonation
if (iu.impersonateValidUser(StringHelper.GetAppSetting("DomainAccount"), StringHelper.GetAppSetting("DomainName"), StringHelper.GetEncryptedAppSetting("DomainAccountPassword")))
{
    NetWorkstationUserEnum nws = new NetWorkstationUserEnum(); //Wrapper for netapi32.dll (Tested on Vista, XP, Win2K, Win2K3, Win2K8)
    string host = nws.DNSLookup(Request.UserHostAddress); // netapi32.dll requires a host name, not an IP address

    string[] users = nws.ScanHost(host); // Gets the users/accounts logged in

    if (nws.ScanHost(host).Length > 0)
    {
        string workstationaccount = string.Empty;

        if (host.IndexOf('.') == -1)  // Pick which account to use, I have 99.9% success with this logic (only time doesn't work is when you run a interactive process as a admin e.g. Run As <process>).
        {
            workstationaccount = String.Format("{0}\\{1}$",StringHelper.GetAppSetting("DomainName"), host).ToUpper();
        }
        else
        {
            workstationaccount = String.Format("{0}\\{1}$", StringHelper.GetAppSetting("DomainName"), host.Substring(0, host.IndexOf('.'))).ToUpperInvariant();
        }

        account = users[users.Length - 1].Equals(workstationaccount) ? users[0] : users[users.Length - 1];

        domain = account.Substring(0, account.IndexOf("\\"));
        user = account.Substring(account.IndexOf("\\") + 1,
                                 account.Length - account.IndexOf("\\") - 1);
    }

    iu.undoImpersonation(); // Disable Impersonation
}

现在使用我们在第一个功能/流程中抓取的帐户,我们现在尝试验证并决定是否应该显示登录信息或自动登录用户。

MembershipUser membershipUser = Membership.GetUser(user);

if (membershipUser != null && membershipUser.IsApproved)
{
    string userRoles = string.Empty;  // Get all their roles
    FormsAuthenticationUtil.RedirectFromLoginPage(user, userRoles, true); // Create FormsAuthTicket + Cookie + 
}

我很久以前写了一篇关于这个的博客文章,这里是我在帖子Source Code Download

中提供的netapi32.dll包装器和我的Impersonation助手的链接

答案 2 :(得分:0)

您不能在同一个ASP.NET应用程序中同时拥有NTLM和FormsAuthentication。您将需要在不同的虚拟目录中使用两个不同的应用程序。