ASP.Net MVC 3登录和Windows身份验证

9
我正在开发一个ASP.Net MVC 3应用程序,其中有一个用户表,存储了用户名和密码。我另外创建了一个ADUsername字段,用于存储Active Directory的域名/用户名。
我想要实现以下两点: 1. 内网用户无需看到登录页面,系统应自动接收他们的域名/用户名并与ADUsername字段进行比较。 2. 外网用户或没有ADUsername值的用户需要查看登录页面,并使用我的自定义用户名和密码字段来登录。
在Visual Studio Development Server上很容易实现,但是在IIS上却非常困难 :)
因为我将Web.Config设置为使用表单认证,所以我使用WindowsIdentity.GetCurrent().Name获取当前的ADUsername,然后查找我的用户表以找到该用户并使用FormsAuthentication.SetAuthCookie对其进行身份验证。
然而,在IIS上始终返回APPPOOL\ASP.NET v4.0用户,而不是我需要的域名/用户名。
有什么帮助吗?

仍在等待一些帮助。我需要表单认证和Windows身份验证一起正常工作,就像描述的那样。 - IoC
2个回答

15
这不是一项容易完成的任务。只有在启用IIS中的Windows身份验证和禁用匿名身份验证时,您才能获得内部网用户的Windows标识。当用户的浏览器访问服务器时,IIS将执行NTLM挑战/响应过程以验证用户。请注意,该挑战/响应实际上发生在每个单独的HTTP请求上,而不仅仅是一次。
这种机制的问题在于,您的Forms身份验证将不再使用,因为它在Windows身份验证运行之后启动,而未能进行身份验证只会触发IIS访问被拒绝 - 而不会回退到Forms身份验证。
要构建混合系统,您需要:
1.设置主Web应用程序以使用Forms身份验证来验证用户。像这样设置Web.config文件。生成自己的机器密钥 - 这是确保cookie共享工作的关键。
<authentication mode="Forms"><forms loginUrl="~/Account/LogOn" timeout="2880" path="/" enableCrossAppRedirects="true" name=".ASPXFORMSAUTH" protection="All"  />
</authentication>
<machineKey validationKey="C50B3C89CB21F4F1422FF158A5B42D0E8DB8CB5CDA1742572A487D9401E3400267682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE" decryptionKey="8A9BE8FD67AF6979E7D20198CFEA50DD3D3799C77AF2B72F" validation="SHA1" /> <system.webServer>
<security>
  <authentication>
    <anonymousAuthentication enabled="true"/>
    <windowsAuthentication enabled="false"/>
  </authentication>
</security></system.webServer>
  • 创建一个新的、独立的Web应用程序,专门用于NTLM身份验证。它将授权然后重定向到主应用程序。抱歉,这两个应用程序不能合并。

  • 在NTLM Web应用程序中,更改web.config身份验证模式如下:

  •     <authentication mode="Windows">       
        </authentication>   
        <machineKey validationKey="C50B3C89CB21F4F1422FF158A5B42D0E8DB8CB5CDA1742572A487D9401E3400267682B202B746511891C1BAF47F8D25C07F6C39A104696DB51F17C529AD3CABE"
                    decryptionKey="8A9BE8FD67AF6979E7D20198CFEA50DD3D3799C77AF2B72F" validation="SHA1" />
    <system.webServer>
        ....
        <security>
          <authentication>
            <windowsAuthentication enabled="true"/>
            <anonymousAuthentication enabled="false"/>
          </authentication>
          <ipSecurity>
            <!-- put whatever here to restrict to your LAN
            <add ..../>
            -->
          </ipSecurity>
        </security>
      </system.webServer>
    
    1. 在 NTLM web 应用程序中,控制器只做一件事——从(WindowsPrincipal)Thread.CurrentPrincipal() 中提取用户名,并调用 FormsAuthentication.SetAuthCookie(..)。然后重定向到主 Web 应用程序。不要使用 WindowsIdentity.GetCurrent(),因为它在未启用模拟的情况下不准确[请参阅 msdn.microsoft.com/en-us/library/ff647076.aspx],而您不希望使用模拟。

    2. 你无法在 Cassini 或 IIS Express 下测试任何这些内容;你必须使用 IIS 7.5。

    3. 前往 IIS 7.5,并为“身份验证 - 匿名”和“身份验证 - Windows”打开特性委派。

    4. 为基于表单的应用程序创建 IIS 应用程序

    5. 右键单击新创建的表单应用程序并选择“添加应用程序”。将路径设置为你的 NTLM 认证应用程序,并将名称设置为“内部认证”之类的名称

    6. 在浏览器中访问http://localhost/YourSite以进行表单身份验证,http://localhost/YourSite/IntranetAuthentication以查看 NTLM 认证,然后通过认证返回到主站点。

    在你的公司中,直接将内部网络用户引导到使用内部认证。外部用户则使用常规表单身份验证页面。


    我需要一个非常小的示例。你能帮我吗? - IoC
    这里涉及的内容太多了,无法在此发布解决方案。我已经为您提交了一个可工作的示例,请访问 https://bitbucket.org/geoffreys/so-dual-win-forms-auth/。 - geoffreys
    该死,刚刚注意到只提交了一半的解决方案。抱歉,明天将提交其余部分。无论如何,它们应该会让你找到正确的方向。 - geoffreys
    很棒的回答! :) 如果您将此添加到Intranet asp.net MVC Web应用程序中,请记得禁用roleManager,否则CurrentPrincipal将是RolePrincipal而不是WindowsPrincipal。 - Moulde

    3
    如果您正在使用混合身份验证,为什么不通过上下文获取AD用户?
      context.Request.ServerVariables["LOGON_USER"] 
    

    我认为IIS配置有问题。确保关闭您的站点上的匿名身份验证,并打开Windows身份验证,如果您想要使用AD身份验证。 - Stefano.net

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接