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

39

创建一个基于Windows域用户验证的ASP.NET MVC应用程序非常容易。同样,创建一个使用Entity Framework存储的个人账户的应用程序也很容易。事实上,这两种情况都有项目模板。

但是我希望在同一个应用程序中同时利用这两种身份验证方式。我尝试将两个项目模板的代码合并。但是我在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身份验证owin中间件似乎会导致域标识失去验证。如果我删除这行代码,域身份验证就可以正常工作。但是没有它,我好像不能支持单独的用户帐户。

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

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


这个答案可以帮助 https://dev59.com/gF0a5IYBdhLWcg3w07vt#30160231 - trailmax
感谢@trailmax。这确实是一个相关的问题,但如果可能的话,我想避免为Active Directory认证用户创建应用程序用户。 - recursive
3
避免在域账户中创建应用程序用户的问题在于,引用这些域账户的特定于应用程序的表看起来会非常奇怪。如果用户在您的应用程序中拥有仅存在于应用程序(而不是域中)的角色,则必须破坏外键约束以适应此情况。特定于应用程序的用户是最好的解决方案。您的应用程序只需对AD进行身份验证,而不是对应用程序进行身份验证。 - jamesSampica
1
最简单的方法是只为身份验证/授权创建2个不同的演示项目。这样做的好处是可以依靠现有的框架和标准配置。从那里开始,您可以选择要么A)为每个互联网用户创建一个AD用户,要么B)为每个AD用户创建一个DB / Internet用户。如果您采用此方法,则B更容易进一步实现。通过身份验证/授权项目后,让所有用户在寻找公共身份验证cookie或通用声明的子域中操作。 - Dave Alperovich
2
如果您想要一个真正统一的解决方案,这是我会开始采用的方法:Install-Package OWIN-MixedAuthhttps://github.com/MohammadYounes/Owin-MixedAuth - Dave Alperovich
显示剩余4条评论
3个回答

15

最简单的方法是只为身份验证/授权创建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,并创建自己的基于声明的 Claims。

AD 用户会得到与 Web 用户相同的基于声明的 Cookie。现在,AD 就像其他第三方认证者(Google、FB、LinkedIN)一样。


7
由于这个原因,我无法使用预制的身份验证解决方案。在我们的项目中,经过多年(以及敏捷方法),我们留下了4种不同的身份验证方式,这很烦人,但我们支持现场所有旧版本的应用程序,所以我们必须保留它们(至少目前是这样)。
最终,我创建了一个工厂来确定身份验证机制(通过任何几种方式,例如令牌格式、其他内容的存在等),然后返回一个包含验证该身份验证方法和设置主体逻辑的包装器。
这在自定义HTTP模块中启动,以便在请求到达控制器之前构建和验证主体。在您的情况下,Windows Auth将是最后的后备方案,我想。在我们的Web API应用程序中,我们采用了相同的方法,但是通过委托处理程序而不是HTTP模块。你可以说这是一种本地令牌联合。当前实现允许我们添加或修改任何验证过程,或添加任何其他令牌格式;最终,用户会获得适当的身份标识或被拒绝。只花了几天时间来实现。

2
对我来说,这个问题的最佳答案似乎是使用身份验证和授权框架。有很多选择(商业和免费)。当然,你可以自己编写,但我不建议这样做。许多非常聪明的人都会做错。
我会看一下IdentityServer3。它肯定不是唯一的解决方案,但它是一个相当不错的身份验证和授权框架。它是开源的,并且很容易快速上手。你的用例是一个常见的用例,你将在上面的链接中找到一些非常有用的信息。授权和身份验证之间的清晰分离,社交身份验证选项,易于使用的 JSON Web 令牌来封装用户声明等。
IdentityServer3允许你配置身份提供者来处理身份验证,并且有很多扩展点,可以处理你的两种情况。从文档中获得:“
IdentityServer支持使用外部身份提供者进行身份验证。外部身份验证机制必须封装在Katana身份验证中间件中。
Katana本身附带了用于Google、Facebook、Twitter、Microsoft帐户、WS-Federation和OpenID Connect的中间件,但也有社区开发的中间件(包括Yahoo、LinkedIn和SAML2p)。
要为外部提供程序配置中间件,请向项目添加一个接受IAppBuilder和字符串作为参数的方法。
IdentityServer3通过浏览器登录窗口支持将AD作为身份提供者,并将通过自定义授权支持更多的编程实现。您还可以查看此处获取有关IdentityServer3和AD身份验证的更多信息。
它还将支持Windows身份验证,您可以查看此处以获取有关实现的信息和示例。
有一个相当不错的入门示例在这里。只要进行正确的配置,IdentityServer3就可以处理您的需求。您需要实现自己的身份验证提供程序并将它们插入框架中,但除此之外没有太多事情要做。至于授权,也有很多选项可供选择。

Brandt,到目前为止,你提供了一个链接并建议使用IdentityServer3或从中学习。但是你真的增加了任何价值吗?这是一个答案还是一个评论? - Dave Alperovich
根据上面的评论,添加了更具体的信息。OP提出了一个细微差别的问题,有很多可能的答案。希望这次编辑提供了足够的信息以便有所帮助。 - Brandt
1
这好多了,并且提供了更多信息。但我没有看到原帖作者有任何细致入微的地方。请求很明确:使用Windows域账户和应用程序管理的账户,更具体地说,如何为两者设置cookie身份验证,因为框架支持不同的解决方案。 - Dave Alperovich
Windows身份验证也已经内置。目前手头没有链接,但我稍后会发布一个(我正在走进一个会议)。 - Brandt
这里有一些关于Windows身份验证集成的有用信息(链接:https://github.com/IdentityServer/WindowsAuthentication)。我现在正在评论(因为我在移动设备上),但稍后我会更新我的答案并在评论中包含链接。 - Brandt
显示剩余5条评论

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