C# Angular应用程序中针对本地AD的身份验证

C# Angular应用程序中针对本地AD的身份验证,c#,angular,asp.net-core,identityserver4,C#,Angular,Asp.net Core,Identityserver4,我一直在开发一个带有.NET核心后端(服务)的Angular应用程序。任务是启用集成身份验证,即使其与本地用户无缝工作,因此我登录到我的(连接到本地AD)计算机一次,web应用程序允许我进入,而无需再次登录。我们一直在使用Identity Server 4,并打算使用它实现此场景 官方网站上有一些关于Windows身份验证(例如针对Active directory)的文档:但没有太多解释。根据我的信息,为了使这个场景工作,浏览器使用Kerberos或NTLM。IS4文档中没有提到这两个方面。我不

我一直在开发一个带有.NET核心后端(服务)的Angular应用程序。任务是启用集成身份验证,即使其与本地用户无缝工作,因此我登录到我的(连接到本地AD)计算机一次,web应用程序允许我进入,而无需再次登录。我们一直在使用Identity Server 4,并打算使用它实现此场景

官方网站上有一些关于Windows身份验证(例如针对Active directory)的文档:但没有太多解释。根据我的信息,为了使这个场景工作,浏览器使用Kerberos或NTLM。IS4文档中没有提到这两个方面。我不了解本地凭据是如何获取的,以及IS4如何“知道”用户属于AD?如何确保只有特定域的用户才能访问我的应用程序

我在这里找到了一些有用的东西,但问题还是一样。即使我可以用我的本地帐户访问该应用程序,我也不明白它的流程


我希望在本地网络中使用应用程序的用户在不输入登录/密码的情况下登录到应用程序(一旦他已经登录到Windows)。这是可以实现的吗?

不确定这是否是您想要的,但我将使用
Active Directory联合身份验证服务
配置
OAuth2端点
,并在.Net核心Web应用程序中获取用户令牌

NTLM身份验证支持是否仅限于非Microsoft浏览器


OAuth2的优点是只使用标准技术。

Identity Server旨在充当身份提供者,如果您需要与广告交谈,您应该看到他们建议使用IAAuthenticationSchemeProvider的联合网关体系结构。其中Identity Server充当端点并与您的广告对话

这是链接:

您可以通过编程方式访问AD并传递正确的凭据以获得身份验证。该步骤应在Identity Server中完成。经过身份验证后,您应该再次重定向到应用程序。 关于你的最后一个问题,答案是肯定的,如果你的网站托管在内部网上,并且你有权访问你的广告,你不需要将你的凭据捕获为用户输入,你可以像我说的那样通过编程访问广告

下面是我用来连接active directory的代码

在ExternalController类中,当您使用IdentityServer时,您会发现:(我不记得我对原始代码做了多少更改,但您应该知道)

//
///启动到外部身份验证提供程序的往返
/// 
[HttpGet]
公共异步任务质询(字符串提供程序、字符串返回URL)
{
if(string.IsNullOrEmpty(returnUrl))returnUrl=“~/”;
//验证返回URL-它是有效的OIDC URL或返回到本地页面
if(Url.IsLocalUrl(returnUrl)==false&&u interaction.IsValidReturnUrl(returnUrl)==false)
{
//用户可能单击了恶意链接-应记录
抛出新异常(“无效返回URL”);
}
if(AccountOptions.WindowsAuthenticationSchemeName==提供程序)
{
//windows身份验证需要特殊处理
return wait ProcessWindowsLoginAsync(returnUrl);
}
其他的
{
//开始挑战并往返返回URL和方案
var props=新的AuthenticationProperties
{
RedirectUri=Url.Action(nameof(Callback)),
项目=
{
{“returnUrl”,returnUrl},
{“方案”,提供者},
}
};
返回挑战(道具、提供者);
}
}
专用异步任务进程WindowsLoginaSync(字符串返回URL)
{
//查看是否已请求windows身份验证并已成功
var result=await HttpContext.authenticateSync(AccountOptions.WindowsAuthenticationSchemeName);
如果(结果?.Principal为WindowsPrincipal wp)
{
//我们将发出外部cookie,然后重定向
//用户返回到外部回调,本质上是测试窗口
//身份验证与任何其他外部身份验证机制相同
var props=新的AuthenticationProperties()
{
RedirectUri=Url.Action(“回调”),
项目=
{
{“returnUrl”,returnUrl},
{“scheme”,AccountOptions.WindowsAuthenticationSchemeName},
}
};
var id=新的ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName);
id.AddClaim(新索赔(JwtClaimTypes.Subject,wp.Identity.Name));
id.AddClaim(新索赔(JwtClaimTypes.Name,wp.Identity.Name));
//将组添加为声明--如果组的数量太多,请小心
if(AccountOptions.IncludeIndowsGroups)
{
var wi=wp.Identity作为WindowsIdentity;
var groups=wi.groups.Translate(typeof(NTAccount));
var roles=groups.Select(x=>newclaim(JwtClaimTypes.Role,x.Value));
id.AddClaims(角色);
}
等待HttpContext.SignInAsync(
IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme,
新的权利要求书(id),
道具);
返回重定向(props.RedirectUri);
}
其他的
{
//触发windows身份验证
    /// <summary>
    /// initiate roundtrip to external authentication provider
    /// </summary>
    [HttpGet]
    public async Task<IActionResult> Challenge(string provider, string returnUrl)
    {
        if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/";

        // validate returnUrl - either it is a valid OIDC URL or back to a local page
        if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false)
        {
            // user might have clicked on a malicious link - should be logged
            throw new Exception("invalid return URL");
        }

        if (AccountOptions.WindowsAuthenticationSchemeName == provider)
        {
            // windows authentication needs special handling
            return await ProcessWindowsLoginAsync(returnUrl);
        }
        else
        {
            // start challenge and roundtrip the return URL and scheme 
            var props = new AuthenticationProperties
            {
                RedirectUri = Url.Action(nameof(Callback)),
                Items =
                {
                    { "returnUrl", returnUrl },
                    { "scheme", provider },
                }
            };

            return Challenge(props, provider);
        }
    }

private async Task<IActionResult> ProcessWindowsLoginAsync(string returnUrl)
        {
            // see if windows auth has already been requested and succeeded
            var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName);
            if (result?.Principal is WindowsPrincipal wp)
            {
                // we will issue the external cookie and then redirect the
                // user back to the external callback, in essence, testing windows
                // auth the same as any other external authentication mechanism
                var props = new AuthenticationProperties()
                {
                    RedirectUri = Url.Action("Callback"),
                    Items =
                    {
                        { "returnUrl", returnUrl },
                        { "scheme", AccountOptions.WindowsAuthenticationSchemeName },
                    }
                };

                var id = new ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName);
                id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.Identity.Name));
                id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name));

                // add the groups as claims -- be careful if the number of groups is too large
                if (AccountOptions.IncludeWindowsGroups)
                {
                    var wi = wp.Identity as WindowsIdentity;
                    var groups = wi.Groups.Translate(typeof(NTAccount));
                    var roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value));
                    id.AddClaims(roles);
                }

                await HttpContext.SignInAsync(
                    IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme,
                    new ClaimsPrincipal(id),
                    props);
                return Redirect(props.RedirectUri);
            }
            else
            {
                // trigger windows auth
                // since windows auth don't support the redirect uri,
                // this URL is re-triggered when we call challenge
                return Challenge(AccountOptions.WindowsAuthenticationSchemeName);
            }
        }