使用OWIN进行混合模式身份验证

时间:2014-02-25 22:37:47

标签: owin

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

要求是,如果某人登录到公司网络或通过VPN连接,我必须在不要求凭据的情况下记录它们。如果用户通过互联网访问网站或者没有AD帐户,我必须使用表单身份验证。

我正在看这个article,但这会与ASP.Net MVC和OWIN一起使用吗?还有其他选择吗?

提前致谢。

2 个答案:

答案 0 :(得分:6)

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

我目前如何实现这一点(请注意,这仍然是一项正在进行的工作),方法如下。我也在使用包含SignInManager的ASP.NET Identity 2.1 alpha(非常酷)。

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

    使用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;
    }
    

    然后可以在你的Login方法中使用它。

    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);
    ...
    

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

答案 1 :(得分:1)

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

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

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

//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);
祝你好运