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

C# 使用Windows域帐户和应用程序管理帐户,c#,asp.net-mvc,asp.net-mvc-5,asp.net-identity,claims-based-identity,C#,Asp.net Mvc,Asp.net Mvc 5,Asp.net Identity,Claims Based Identity,创建基于windows域用户身份验证的ASP.NET MVC应用程序很容易。创建一个使用使用使用实体框架存储的单个帐户的帐户也很容易。事实上,两者都有项目模板 但是我想在同一个应用程序中同时使用两种身份验证。我尝试将两个项目模板中的代码组合起来。我在Startup.Auth.cs中遇到问题 // from "Individual Accounts" template app.UseCookieAuthentication(new CookieAuthenticationOptions {

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

但是我想在同一个应用程序中同时使用两种身份验证。我尝试将两个项目模板中的代码组合起来。我在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))
    }
});
//来自“个人账户”模板
app.UseCookieAuthentication(新的CookieAuthenticationOptions
{
AuthenticationType=DefaultAuthenticationTypes.ApplicationOkie,
LoginPath=新路径字符串(“/Account/Login”),
Provider=新CookieAuthenticationProvider
{
OnValidateIdentity=SecurityStampValidator.OnValidateIdentity(
validateInterval:TimeSpan.FromMinutes(30),
regenerateIdentity:(管理器,用户)=>user.GenerateUserIdentityAsync(管理器))
}
});
中间件中cookie身份验证的存在似乎会导致域标识未经身份验证。如果我去掉这一行,域身份验证就工作了。但没有它,我似乎无法支持个人用户帐户

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


如何使用ASP.net identity framework允许我的应用程序对来自windows域或特定于应用程序的用户存储的用户进行身份验证?

正是由于这个原因,我无法使用预烘焙的解决方案进行身份验证。在我们的项目中,过去的几年(以及敏捷方法)给我们留下了4种不同的身份验证方法,这很烦人,但我们支持该领域中所有遗留版本的应用程序,因此我们必须保留所有这些(至少现在是这样)

我最终创建了一个工厂,该工厂负责找出身份验证机制(通过令牌格式、是否存在其他内容等多种方式中的任何一种),然后返回一个包装器,该包装器包含验证身份验证方法和设置主体的逻辑


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

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

这样做的优点是依赖于现有的框架和标准配置

从那里,您决定

  • 为每个internet用户创建一个广告用户,或
  • 为每个广告用户创建一个DB/Internet用户
为每个广告用户创建一个身份用户更容易进一步实现。这样,整个应用程序中就可以存在相同的cookie和过滤器

在这种情况下,您可以

  • 使用应用程序的子域
  • AD Authentication项目可以具有身份验证/授权的单一目的,然后Web应用程序可以代表应用程序的其余部分


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

在MixedAuth中安装软件包OWIN

Web.config中

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

:

工作原理: 处理程序使用
ApplyResponseChallengeAsync
确认请求是401质询。如果是这样,它将重定向到回调路径,以从配置为查询AD的IIS请求身份验证

        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);
    }
protected async override System.Threading.Tasks.Task
AuthenticateCoreAsync()
{
AuthenticationProperties=UnpackStateParameter(Request.Query);
如果(属性!=null)
{
var logonUserIdentity=Options.Provider.GetLogonUserIdentity(上下文);
if(logonUserIdentity.AuthenticationType!=Options.CookieOptions.AuthenticationType
&&logonUserIdentity.IsAuthenticated)
{
AddCookieBackIfExists();
ClaimsIdentity ClaimsIdentity=新的ClaimsIdentity(
logonUserIdentity.Claims、Options.SignInAsAuthenticationType);
//ExternalLoginInfo GetExternalLoginInfo(AuthenticateResult结果)
claimsIdentity.AddClaim(新索赔)(ClaimTypes.NameIdentifier,
logonUserIdentity.User.Value,null,Options.AuthenticationType));
//可以从广告中抓取电子邮件并将其添加到索赔列表中。
var票证=新的身份验证票证(索赔实体、属性);
var context=新的MixedAuthenticatedContext(
上下文
索赔性,
属性,
Options.AccessTokenFormat.Protect(票证));
wait Options.Provider.Authenticated(上下文);
回程票;
}
}
返回新的AuthenticationTicket(空,属性);
}
AuthenticateCoreAsync
使用
AddCookieBackIfExist
    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);
    }