1

我正在尝试使用 Windows 身份验证凭据将我的本机(Winforms、控制台应用程序)客户端连接到托管在IIS上的 Identity Server 。重点是让用户通过 AD 进行身份验证,并使用这些凭据从身份服务器(通过商业https://commercial.abp.io/平台运行)获得正确的声明和角色。

编辑:我发现这不是与客户端相关的问题,因为即使直接在托管站点上我也无法使用我的外部登录名(Windows 凭据)。

这个东西在由IISExpress托管时在本地工作,然后我将它发布到IIS并在 IIS 设置中启用了匿名和 Windows 身份验证,这就是问题开始的地方。

我的登录屏幕

当我运行它并单击外部登录(Windows 凭据)按钮时,我通常会重定向到https://myserver/Error?httpStatusCode=401 并且我会提示我的 Windows 凭据(即使我正确插入,只需重复提示再次)。

这是我单击自动 Windows 身份验证按钮后得到的地方

我不时使用我的 Windows 凭据登录(这是目标)。使用用户名和密码登录可以正常工作。

我在这里看到有人提到的类似问题: https ://github.com/IdentityServer/IdentityServer4/issues/4937没有任何解决方案\答案。

我的客户端基本上是来自此 https://github.com/damienbod/AspNetCoreWindowsAuth的示例 NativeConsolePKCEClient

static string _authority = "https://myserver/";
string redirectUri = "https://127.0.0.1:45656";

        var options = new OidcClientOptions
        {
            Authority = _authority,
            ClientId = "native.code",
            ClientSecret = "secret",
            RedirectUri = redirectUri,
            Scope = "openid profile",
            FilterClaims = false,
            Browser = browser,
            Flow = OidcClientOptions.AuthenticationFlow.AuthorizationCode,
            ResponseMode = OidcClientOptions.AuthorizeResponseMode.Redirect,
            LoadProfile = true
        };

        _oidcClient = new OidcClient(options); 
         var result = await _oidcClient.LoginAsync();

在服务器端启动配置服务:

        private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
    {
        context.Services.Configure<IISOptions>(iis =>     // IISOptions
        {
            iis.AuthenticationDisplayName = "Windows";
            iis.AutomaticAuthentication = false;
        });

        context.Services.AddAuthentication()
            .AddJwtBearer(options =>
            {
                options.Authority = configuration["AuthServer:Authority"];
                options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); ;
                options.Audience = "ABPIdentityServer";
            });
    }

这是 ProcessWindowsLoginAsync 质询方法:

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

            var id = new ClaimsIdentity(Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme);
            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
            {
                var wi = (WindowsIdentity)wp.Identity;
                var groups = wi.Groups.Translate(typeof(NTAccount));
                var roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value));
                id.AddClaims(roles);
            }

            await HttpContext.SignInAsync(IdentityConstants.ExternalScheme, 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("Windows");
        }
    }

我怀疑这段代码在调用 Challenge 时会以某种方式返回重定向到错误页面,但我不确定,我现在知道为什么。

那我错过了什么?是否可以在 IIS 上同时运行 Windows 和匿名身份验证?

在这里我也发现了类似的问题: identity server 4 windows authentication

但提出的答案对我没有帮助。

4

2 回答 2

0

我强烈怀疑这不是客户端问题,而是令牌提供者的问题(不是 ID4 库,而是您安装了 ID4 库的库)。

我相信您已经在AccountController->Login操作中添加了以下代码,但请确保您在其中添加了成功检查,如果您错过了,那么您的应用程序将进入无限循环

[HttpGet] public async Task<IActionResult> Login(string returnUrl)
{
 if(loginViewModel.ExternalLoginScheme == "Windows")
 {
   var authenticationResult = await HttpContext.AuthenticateAsync("Windows").ConfigureAwait(false);
   if (authenticationResult.Succeeded && authenticationResult?.Principal is WindowsPrincipal windowsPrinciple)
   {
     // Add your custom code here
     var authProps = new AuthenticationProperties()
                {
                    RedirectUri = Url.Action("Callback"),
                    Items =
                    {
                        { "returnUrl", returnUrl },
                        { "scheme", "Windows"},
                    }
                };

    await HttpContext.SignInAsync();

    return Redirect(RedirectUri);
   }
   else
   {
     return Challenge("Windows");
   }
  }
}

我希望这可以帮助您解决问题。编码快乐!!

于 2020-12-31T13:49:57.020 回答
0

仅适用于任何可能感兴趣的人。我发现了导致重定向错误的原因。

它以某种方式与我用于生成基本应用程序的 ABP 套件相关联。在 ApplicationInitialization 中有一个名为的中间件

app.UseErrorPage();

当 Windows 凭据受到挑战时,将其视为错误并重定向到 https://myserver/Error?httpStatusCode=401。

我不确定这个中间件是如何工作的以及为什么有时登录有效,但删除这部分解决了我的问题。

我希望这对某人有所帮助,不知何故,有时..

于 2021-01-11T08:35:37.860 回答