我正在尝试使用 Windows 身份验证凭据将我的本机(Winforms、控制台应用程序)客户端连接到托管在IIS上的 Identity Server 。重点是让用户通过 AD 进行身份验证,并使用这些凭据从身份服务器(通过商业https://commercial.abp.io/平台运行)获得正确的声明和角色。
编辑:我发现这不是与客户端相关的问题,因为即使直接在托管站点上我也无法使用我的外部登录名(Windows 凭据)。
这个东西在由IISExpress托管时在本地工作,然后我将它发布到IIS并在 IIS 设置中启用了匿名和 Windows 身份验证,这就是问题开始的地方。
当我运行它并单击外部登录(Windows 凭据)按钮时,我通常会重定向到https://myserver/Error?httpStatusCode=401 并且我会提示我的 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
但提出的答案对我没有帮助。