ASP.NET Core 3.0:如何将现有身份验证转发给另一个请求 - 双跳问题?
ASP.NET Core 3.0: How to forward an existing authentication to another request - double hop problem?
我遇到了以下情况(所有应用程序和服务都在 Windows 上使用 asp.net 核心 3.0):
我有一个在 AppUser 上下文中运行的客户端应用程序。它使用 HttpClient 向在 WebUser 上下文中运行的 WebServiceA 发送请求。
该请求使用 Windows 身份验证。
var credentialsCache = new CredentialCache { { uri, "Negotiate", CredentialCache.DefaultNetworkCredentials } };
var handler = new HttpClientHandler { Credentials = credentialsCache };
var httpClient = new HttpClient(handler);
在 WebServiceA 中,调用被正确接收并经过身份验证:
HttpContext.User.Identity.IsAuthenticated
为真,HttpContext.User.Identity.Name
为 AppUser。
为了能够处理请求,WebServiceA 必须向 WebServiceB 发送另一个请求。 此请求还必须作为 AppUser.
进行身份验证
目前我正在使用以下代码创建向 WebServiceB 发出请求的 HttpClient:
var credentialsCache = new CredentialCache { { uri, "Negotiate", CredentialCache.DefaultNetworkCredentials } };
HttpClientHandler handler = new HttpClientHandler
{
Credentials = credentialsCache,
UseDefaultCredentials = true
};
HttpClient httpClient = new HttpClient(handler);
问题是,调用始终被验证为 WebUser(运行服务的人),而不是 AppUser(发送请求的人)。
我认为 DefaultNetworkCredentials 始终是经过身份验证的用户的。
我如何发送(从 WebRequest 中)另一个 WebRequest 到另一个 WebService,该 WebService 已通过提交原始请求的同一用户进行身份验证?
有没有办法将身份验证从一个 WebService 传递到另一个 WebService?
关于 Kerberos 和 AD:
WebServiceA 和 WebServiceB 在同一域中的不同服务器上 运行。它们不是托管在 IIS 中,而是托管在 Windows 服务中。
我尝试按照此处所述设置 SPN:
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.0&tabs=visual-studio
setspn -S HTTP/ServerA.domain domain\WebUser
也试过:
setspn -a WebServiceA/WebUser domain\WebUser
但是没有成功。
经过三天的网络研究和尝试,我的头晕了...
如何将 UserCredentials 放入第二个请求中?
还是因为(可能是错误的?)AD 配置 (SPN),WebService 总是默默地获取启动服务的用户的凭据?
感谢每一个提示!
史蒂菲
OP 在评论中接受的答案涉及假冒。根据这个 blog entry 可以在 .Net Core 中使用 WindowsIdentity.RunImpersonated
:
// The user to be impersonated
var userToImpersonate = (WindowsIdentity)HttpContext.User.Identity;
// Impersonating the current Windows user [HttpContext.User.Identity]...
var result = await WindowsIdentity.RunImpersonated(
userToImpersonate.AccessToken, async () =>
{
// This time WindowsIdentity.GetCurrent() will retrieve the impersonated
// user with its claims...
var impersonatedUser = WindowsIdentity.GetCurrent().Name;
// Your business logic code here...
});
我遇到了以下情况(所有应用程序和服务都在 Windows 上使用 asp.net 核心 3.0):
我有一个在 AppUser 上下文中运行的客户端应用程序。它使用 HttpClient 向在 WebUser 上下文中运行的 WebServiceA 发送请求。 该请求使用 Windows 身份验证。
var credentialsCache = new CredentialCache { { uri, "Negotiate", CredentialCache.DefaultNetworkCredentials } };
var handler = new HttpClientHandler { Credentials = credentialsCache };
var httpClient = new HttpClient(handler);
在 WebServiceA 中,调用被正确接收并经过身份验证:
HttpContext.User.Identity.IsAuthenticated
为真,HttpContext.User.Identity.Name
为 AppUser。
为了能够处理请求,WebServiceA 必须向 WebServiceB 发送另一个请求。 此请求还必须作为 AppUser.
进行身份验证目前我正在使用以下代码创建向 WebServiceB 发出请求的 HttpClient:
var credentialsCache = new CredentialCache { { uri, "Negotiate", CredentialCache.DefaultNetworkCredentials } };
HttpClientHandler handler = new HttpClientHandler
{
Credentials = credentialsCache,
UseDefaultCredentials = true
};
HttpClient httpClient = new HttpClient(handler);
问题是,调用始终被验证为 WebUser(运行服务的人),而不是 AppUser(发送请求的人)。
我认为 DefaultNetworkCredentials 始终是经过身份验证的用户的。
我如何发送(从 WebRequest 中)另一个 WebRequest 到另一个 WebService,该 WebService 已通过提交原始请求的同一用户进行身份验证? 有没有办法将身份验证从一个 WebService 传递到另一个 WebService?
关于 Kerberos 和 AD: WebServiceA 和 WebServiceB 在同一域中的不同服务器上 运行。它们不是托管在 IIS 中,而是托管在 Windows 服务中。
我尝试按照此处所述设置 SPN: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.0&tabs=visual-studio
setspn -S HTTP/ServerA.domain domain\WebUser
也试过:
setspn -a WebServiceA/WebUser domain\WebUser
但是没有成功。
经过三天的网络研究和尝试,我的头晕了... 如何将 UserCredentials 放入第二个请求中? 还是因为(可能是错误的?)AD 配置 (SPN),WebService 总是默默地获取启动服务的用户的凭据?
感谢每一个提示!
史蒂菲
OP 在评论中接受的答案涉及假冒。根据这个 blog entry 可以在 .Net Core 中使用 WindowsIdentity.RunImpersonated
:
// The user to be impersonated
var userToImpersonate = (WindowsIdentity)HttpContext.User.Identity;
// Impersonating the current Windows user [HttpContext.User.Identity]...
var result = await WindowsIdentity.RunImpersonated(
userToImpersonate.AccessToken, async () =>
{
// This time WindowsIdentity.GetCurrent() will retrieve the impersonated
// user with its claims...
var impersonatedUser = WindowsIdentity.GetCurrent().Name;
// Your business logic code here...
});