【问题标题】:Mixed mode authentication with OWIN使用 OWIN 的混合模式身份验证
【发布时间】:2014-08-05 06:19:03
【问题描述】:

我正在构建一个 MVC 5 应用程序。我需要根据 AD 和 sql 数据库或 Web 服务对人员进行身份验证。

要求是如果一个人登录到公司网络或通过 VPN 连接,我必须登录他们而不要求提供凭据。如果用户通过 Internet 访问该网站或某人没有 AD 帐户,我必须使用表单身份验证。

我正在查看这个article,但这是否适用于 ASP.Net MVC 和 OWIN?还有其他选择吗?

提前致谢。

【问题讨论】:

    标签: owin


    【解决方案1】:

    我现在也在做一些非常相似的事情。我正在为内部和外部用户提供单点登录门户,他们可以使用他们的 AD 帐户或指定的用户/密码组合登录。

    我目前是如何实现这一点的(请注意,这仍在进行中)是通过以下方式实现的。我还在使用包含 SignInManager 的 ASP.NET Identity 2.1 alpha(非常酷)。

    1. 使用可选密码设置用户帐户(必须为非 AD 用户指定)
    2. 将 UserLogin 与 AD 用户的帐户相关联,其中 ProviderKey 等于他们的 AD 帐户 Sid
    3. 在登录时,我检测Request.LogonUserIdentity 是否有一个已知帐户。然后使用UserManager.FindAsync 方法检查它们是否有效。您可以在此处再次挑战他们,为他们提供直接以已知用户身份登录或直接登录的选项(您在此处选择)。
    4. 然后我还允许他们通过标准用户登录表单登录,方法是检测以域\用户名格式输入的用户名。这允许域用户在从外部或从其他用户计算机进入您的站点时登录。

    此过程中的一些代码 sn-ps(这些只是一些示例,因为完整的解决方案已在我的解决方案中展开,因此您可以继续使用这些示例)。

    使用 Request.LoginUserIdentity 登录。这可能是您帐户控制器中的一个方法。

    public async Task<ActionResult> WindowsLogin(string returnUrl)
    {
        var loginInfo = GetWindowsLoginInfo();
        var user = await _userManager.FindAsync(loginInfo);
        if (user != null)
        {
            await SignInAsync(user, false);
            return RedirectTo(returnUrl, "Manage");
        }
    
        return RedirectToAction("Login");
    }
    
    private UserLoginInfo GetWindowsLoginInfo()
    {
        if (Request.LogonUserIdentity == null || Request.LogonUserIdentity.User == null)
        {
            return null;
        }
        return new UserLoginInfo("Windows", Request.LogonUserIdentity.User.ToString());
    }
    

    我还在我的 ApplicationSignInManager 中添加了一个方法(从 SignInManager 继承),以允许用户使用标准登录表单使用其 AD 详细信息登录。

    public async Task<SignInStatus> WindowsLoginAsync(string userName, string password, bool isPersistent)
    {
        var signInStatus = SignInStatus.Failure;
    
        using (var context = new PrincipalContext(ContextType.Domain, "YourDomain"))
        {
            // validate the credentials
            bool credentialsValid = context.ValidateCredentials(userName, password);
    
            if (credentialsValid)
            {
                UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(context, userName);
                if (userPrincipal != null)
                {
                    var loginInfo = new ExternalLoginInfo
                    {
                        Login = new UserLoginInfo(AuthenticationTypes.Windows, userPrincipal.Sid.ToString())
                    };
                    signInStatus = await ExternalSignInAsync(loginInfo, isPersistent);
                }
            }
        }
        return signInStatus;
    }
    

    那么这可以像这样在你的登录方法中使用。

    Regex domainRegex = new Regex("(domain\\.+)|(.+@domain)");
    if (domainRegex.IsMatch(model.Username))
    {
        result = await _signInManager.WindowsLoginAsync(model.Username, model.Password, model.RememberMe);
        switch (result)
        {
            case SignInStatus.Success:
                return RedirectTo(returnUrl, "Manage");
        }
    }
    
    result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, true);
    ...
    

    我希望其中的一些可以帮助您解决问题!

    【讨论】:

    • 感谢您。我被 owin 混合模式身份验证卡住了一段时间。 Request.LogonUserIdentity.User 解决了这个问题。即使没有在 IIS 中启用 WindowsAuthentication,它也会提供 Windows 用户。
    • @jerms55 我在尝试您的代码时遇到错误。“名称 '_userManager' 在当前上下文中不存在”和“名称 'RedirectTo' 在当前上下文中不存在”。任何想法可以做什么。谢谢。
    • @ary RedirectTo 是我的基本控制器中的一个辅助方法,它验证 returnUrl(不是另一个域)然后重定向到它,或者如果它无效则返回一个 RedirectToAction_userManager 是注入到我的控制器中的 Microsoft.AspNet.Identity.UserManager&lt;TUser, TKey&gt; 类的一个实例。
    • 谢谢@jerms55。您能否提供有关如何将现有的基于 MVC 5 表单的身份验证网站转换为 Windows 身份验证的分步提示。我确实在这里提出了问题。但没有得到好的答案。我对这一切都很陌生,所以真的需要一步一步的帮助。谢谢。
    【解决方案2】:

    owin 的工作方式是每个请求都会通过启动时注册的所有中间件模块。

    这意味着,如果您希望有多种方式进行身份验证,则需要使用/创建和注册所需的所有不同中间件。然后,每个中间件将针对各种用户存储进行身份验证,并创建一个 ClaimsPrincipal(或多个)。

    一个简单的例子,(面向 api)看起来像这样。 OAuthBearer 是来自 Identity 2.0 的令牌身份验证,而 BasicAuthenication 只是标头中的基本用户/密码。

    //This will create the usermanager per request.
    app.CreatePerOwinContext(ApplicationSession.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    
    // Token Authentication
    app.UseOAuthBearerAuthentication(OAuthBearerOptions);
    
    // Basic Authentication.
    app.UseBasicAuthentication(app.CreateLogger<BasicAuthenticationMiddleware>(), 
                        "Realm", ValidateUser);
    

    祝你好运

    【讨论】:

      猜你喜欢
      • 2014-01-28
      • 2015-07-18
      • 2019-09-08
      • 2012-10-23
      • 1970-01-01
      • 1970-01-01
      • 2018-06-04
      • 2013-04-14
      • 2011-01-26
      相关资源
      最近更新 更多