【问题标题】:ASP.Net MVC - OWIN - Allowing Windows/Individual AuthenticationASP.Net MVC - OWIN - 允许 Windows/个人身份验证
【发布时间】:2017-08-16 17:33:19
【问题描述】:

我有一个 ASP.Net MVC 5 应用程序,该应用程序当前正在使用个人身份验证(没有身份验证/匿名访问的帐户/login.cshtml 页面)和 OWIN。工作正常。

由于这是一个 Intranet 应用程序,我希望允许用户在其 windows 帐户、其他用户 windows 帐户或应用程序帐户(管理员、特殊用户等 - 这些帐户没有关联的域帐户)下登录。

对于第一个选项,我想在登录屏幕上显示他们的 Windows 用户名,他们只需单击“确定”按钮即可登录。为了获取用户名,我修改了 Visual Studio 项目属性以禁用匿名身份验证并启用 Windows 身份验证。还修改了 web.config 并将身份验证模式设置为 Forms。这会导致“HTTP 错误 404.15 - 未找到”。这似乎是由 OWIN 引起的身份验证循环造成的,需要修复以下建议:

  • 确保登录控制器方法允许匿名访问(默认情况下似乎是这种方式)。
  • 或修改 Startup.auth,注释掉 LoginPath 属性。
  • 或修改web.config,添加值为“false”的appSetting“owin:AutomaticAppStartup”。

我选择了 LoginPath 修复,这似乎有效(web.config 更改也是如此),因为没有错误并且登录页面显示为 Windows 用户名(使用 System.Threading.Thread.Currentprinciple.Identity 检索。名称)。

现在的问题是,一旦用户登录,OwinContext 就没有用户了(HttpContext.GetOwinContext().GetUserManager())。

理想情况下,我不需要 IIS 或 OWIN 进行任何身份验证,因为它由应用程序完成 - 但我需要初始请求(针对帐户/登录页面)包含 Authenticate 标头,以便我可以获取 Windows 用户。

首先,我想了解导致“HTTP 错误 404.15”的原因并进行修复。 其次,如何让 OWIN 处理身份验证更改 - 我只需要它来持久化用户以进行控制器身份验证。

【问题讨论】:

    标签: c# asp.net-mvc authentication


    【解决方案1】:

    这只是一个猜测,但我认为该错误是由您描述的错误配置引起的:您已将身份验证模式设置为“表单”,但将项目设置为使用 Windows 身份验证。这可能会令人困惑,但 Windows 身份验证不是表单身份验证。当您使用表单身份验证时,用户在提交的表单中提供凭据,针对用户存储进行验证(包括所有防伪优点)(我相信您使用的是 ASP.NET 身份,这将是“个人身份验证”的默认设置" 设置),如果验证成功,则响应中包含要设置的 cookie。然后使用此 cookie 来验证进一步的请求。

    正如Katana documentation 所证实的,没有用于 Windows 身份验证的内置中间件 - 微软只是假设应该使用 IIS。这有效地阻止了我们轻松将 Katana OWIN 中间件提供程序与 Windows 身份验证相结合。现在,关键词很简单:我们仍然可以“破解”它。

    不幸的是,它仍然是一个 hack:我还没有找到使身份验证“透明”的方法(如“用户打开登录表单并可以输入 AD 帐户凭据或个人帐户凭据,一切正常“)。您将需要维护每个 Windows 用户的个人帐户记录(就像您对任何外部 OWIN 中间件所做的那样,例如 Google 或 Facebook)。不过,您可以自动化帐户创建和关联,并使其看起来透明。您可以为 Windows 身份验证添加“外部提供程序”按钮。

    对用户进行身份验证看起来像(在单独的“AD 身份验证”控制器中):

    bool userWindowsAuthentication = Request.LogonUserIdentity.IsAuthenticated;
    
    if (userWindowsAuthentication) {
        var userStoreDatabaseContext = new ApplicationDbContext();
        var userStore = new UserStore<UserModel>(userStoreDatabaseContext);
        var userStoreManager = new UserManager<UserModel>(userStore);
        var userWindowsLoginCredentials = GetWindowsLoginInfo();
    
        var existingInternalUser = userStoreManager.FindAsync(userWindowsLoginCredentials.UserName)
    
        if (existingInternalUser) {
           // It means that the user already exists in the internal provider and here you simply authenticate and redirect to destination
        } else {
           // It means that the user does not exist. You can automatically create the internal user record here and associate the Windows user with the internal record.
        }
    } else {
        // It means that user is not signed in using Windows authentication, so you either want to redirect back to the login page or restrict access or do something else
    }
    

    如您所见,它很“脏”。另一个技巧:您可以拥有仅接受 Windows 身份验证的附加层(单独的应用程序或虚拟应用程序)。这个应用程序可以成为您的登录资源。如果用户通过 Windows AD 进行身份验证,您可以将他们重定向到正确的登录页面。您可以更进一步,在重定向请求标头中添加他们的登录信息,但如果您这样做 - 标头必须加密以确保 Windows 身份验证不会被伪造,并且唯一应该能够解密和验证它的应该是您的主要应用。再次,肮脏,但有效。

    【讨论】:

    • 感谢 Phil.P 的快速回复。我已经尝试过 Forms 和 Windows Authentication 并且都产生了相同的结果。请注意 - 我需要 Windows 身份验证的只是在初始请求中传递客户端用户名 - 然后我对数据库中的用户表和 LDAP 查询进行身份验证(如果是 Windows 用户)。
    • @Leigh.D 您将如何针对 LDAP 进行验证?是什么阻止我作为一名黑客用已知的 Windows 用户名替换我传递的任何内容并有效地进行身份验证? Windows 身份验证是指验证实际用户身份验证的 NTLM。您必须在“使用个人帐户”中设置表单、项目设置,并为 Windows 身份验证使用额外的身份验证端点/中间件。
    猜你喜欢
    • 2015-07-18
    • 2014-01-02
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-08
    • 2015-01-31
    相关资源
    最近更新 更多