使用Windows域帐户和应用程序管理的帐户

时间:2015-05-12 19:53:53

标签: c# asp.net-mvc asp.net-mvc-5 asp.net-identity claims-based-identity

可以轻松创建基于Windows域用户进行身份验证的 ASP.NET MVC 应用程序。创建一个使用实体框架存储的个人帐户也很容易。事实上,两者都有项目模板。

但我想在同一个应用程序中使用 BOTH 种类的身份验证。我试图结合两个项目模板的代码。我在Startup.Auth.cs中遇到了问题。

// from "Individual Accounts" template
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider
    {
        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
            validateInterval: TimeSpan.FromMinutes(30),
            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
    }
});

中间件中存在cookie身份验证似乎会导致域身份未经身份验证。如果我采用此行,域身份验证将起作用。但没有它,我似乎无法支持个人用户帐户。

我已经下载了katana项目源代码并检查了CookieAuthenticationHandler.cs,但我不太明白它是如何在OWIN管道的上下文中运行的。

如何使用ASP.net身份框架允许我的应用程序从Windows域或特定于应用程序的用户存储中验证用户?

3 个答案:

答案 0 :(得分:16)

最简单的方法是将2个不同的演示项目仅用于身份验证/授权。

这具有依赖现有框架和标准配置的优势。

从那里开始,您决定

  • 为每个互联网用户创建一个AD用户,或
  • 为每个AD用户创建一个DB / Internet用户。

为每个AD用户创建Identity用户更容易实现。然后,整个应用程序中可以存在相同的cookie和过滤器。

在这种情况下,您可以

  • 为您的应用使用子域名
  • AD认证项目可以具有认证/授权的单一目的,然后Web应用程序可以代表您应用的其余部分。

或者,如果您想要一个真正的统一解决方案,请使用MohammadYounes / Owin-MixedAuth

MohammadYounes/Owin-MixedAuth

Install-Package OWIN-MixedAuth

Web.config

<location path="MixedAuth">
  <system.webServer>
    <security>
      <authentication>
        <windowsAuthentication enabled="true" />
      </authentication>
    </security>
  </system.webServer>
</location>

在Startup.Auth.cs

app.UseMixedAuth(cookieOptions);

工作原理:

处理程序使用ApplyResponseChallengeAsync确认请求是 401挑战 。如果是,则重定向到回调路径以从IIS请求身份验证,该IIS配置为查询AD。

        AuthenticationResponseChallenge challenge = Helper.LookupChallenge(
              Options.AuthenticationType, Options.AuthenticationMode);

401质询 是由未经授权的用户尝试使用需要身份验证的资源引起的

处理程序使用InvokeAsync检查请求是否来自回调路径(IIS),然后调用AuthenticateCoreAsync

    protected async override System.Threading.Tasks.Task<AuthenticationTicket>
                AuthenticateCoreAsync()
    {
        AuthenticationProperties properties = UnpackStateParameter(Request.Query);

        if (properties != null)
        {
            var logonUserIdentity = Options.Provider.GetLogonUserIdentity(Context);

            if (logonUserIdentity.AuthenticationType != Options.CookieOptions.AuthenticationType
                && logonUserIdentity.IsAuthenticated)
            {
                AddCookieBackIfExists();

                ClaimsIdentity claimsIdentity = new ClaimsIdentity(
                    logonUserIdentity.Claims, Options.SignInAsAuthenticationType);

                //  ExternalLoginInfo GetExternalLoginInfo(AuthenticateResult result)
                claimsIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier,
                  logonUserIdentity.User.Value, null, Options.AuthenticationType));

                //could grab email from AD and add it to the claims list.
                var ticket = new AuthenticationTicket(claimsIdentity, properties);

                var context = new MixedAuthAuthenticatedContext(
                   Context,
                   claimsIdentity,
                   properties,
                   Options.AccessTokenFormat.Protect(ticket));

                await Options.Provider.Authenticated(context);

                return ticket;
            }
        }
        return new AuthenticationTicket(null, properties);
    }

AuthenticateCoreAsync使用AddCookieBackIfExists来阅读AD创建的声明Cookie,并创建自己的声明。

为AD用户提供与Web用户相同的基于声明的Cookie。 AD现在与任何其他第三方身份验证器一样( Google,FB,LinkedIN

答案 1 :(得分:7)

由于这个原因,我还没有能够使用预先烘焙的解决方案进行身份验证。在我们的项目中,过去的几年(和敏捷方法)让我们有4种不同的方式来进行身份验证,这很烦人,但我们支持该领域的所有旧版应用程序,因此我们必须保留所有这些(至少目前为止)。

我最终创建了一个工厂,它确定了身份验证机制(通过令牌格式,存在其他一些东西),然后返回一个包装器,其中包含验证该身份验证方法和设置主体的逻辑。

这将在自定义 HTTP模块中启动,以便在请求到达控制器之前构建和验证主体。在你的情况下,我认为Windows Auth将是最终的后备。在我们的 Web API 应用程序中,我们采用相同的方法,但通过委托处理程序而不是 HTTP模块。你可以说,它是一种本地令牌联合。当前实现允许我们添加或修改任何验证过程,或添加任何其他令牌格式;最后,用户最终会获得适当的身份或被拒绝。只用了几天就实现了。

答案 2 :(得分:2)

在我看来,这个问题的最佳答案是使用身份验证和授权框架。有很多可供选择(商业和免费)。当然,你可以写自己的,但我会劝阻它。很多非常聪明的人都错了。

我会看看IdentityServer3。它当然不是唯一的解决方案,但它是一个非常好的身份验证和授权框架。它是开源的,很容易快速启动和运行。您的用例很常见,您可以在上面的链接中找到一些非常有用的信息。清除授权和身份验证之间的分离,社交身份验证选项,易于使用封装用户声明的json Web令牌等。

它如何帮助您

IdentityServer3允许您配置Identity Providers来处理身份验证,并且有许多扩展点可以让您实现可以处理两种方案的责任链。来自docs

  

IdentityServer支持使用外部身份提供程序进行身份验证。外部认证机制必须封装在Katana认证中间件中。

     

Katana本身附带谷歌,Facebook,Twitter,微软账户,WS-Federation和OpenID Connect的中间件 - 但也有社区开发的中间件(包括Yahoo,LinkedIn和SAML2p)。

     

要为外部提供程序配置中间件,请在项目中添加一个接受IAppBuilder和字符串作为参数的方法。

IdentityServer3通过浏览器登录窗口支持AD作为身份提供者,并将通过custom grant支持更具编程性的实现。您还可以查看here以获取有关IdentityServer3和AD身份验证的更多信息。

它也将支持Windows身份验证,您可以查看here以获取有关实现该功能的信息和示例。

还有一个非常好的入门示例here

通过正确的配置,IdentityServer3可以满足您的要求。您将需要实现自己的身份验证提供程序并将它们插入到框架中,但除此之外没有更多内容。至于授权,那里也有很多选择。