我有以下情况:
WPF client application -> WCF Service -> WebApi Service
我希望能够在 WebApi 服务中对客户端应用程序的用户进行身份验证。 我不需要完全模拟/委派 - 我只需要客户端的登录 ID,因为我将用户 ID 用于第三方授权系统。 WCF 服务和 Web API 服务位于同一台服务器上。
我正在尝试的当前方法是模拟WindowsIdentity,如下所示。
1. 与欧文自托管的WebApi服务
WebApp.Start(options,
builder =>
{
// Authenticate POST requests, but not GET requests
// Adapted from: http://stackoverflow.com/questions/17457382/windows-authentication-with-signalr-and-owin-self-hosting
var listener = (HttpListener)builder.Properties[typeof(HttpListener).FullName];
listener.AuthenticationSchemes =
AuthenticationSchemes.Negotiate | AuthenticationSchemes.Anonymous;
listener.AuthenticationSchemeSelectorDelegate =
request => (request.HttpMethod == HttpMethod.Get.Method)
? AuthenticationSchemes.Anonymous
: AuthenticationSchemes.Negotiate;
// etc
});
2. 周转基金服务
<system.web>
: <authentication mode="Windows" />
在<bindings>
:
<binding name="BasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
在我想模拟的特定函数的代码中:
WindowsIdentity callerIdentity = ServiceSecurityContext.Current.WindowsIdentity;
using (callerIdentity.Impersonate())
{
var request = ...;
request.ImpersonationLevel = TokenImpersonationLevel.Impersonation;
request.UseDefaultCredentials = true;
// Use request to call Web Api
}
3. 在客户端中:
<endpointBehaviors>
<behavior name="ImpersonationBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
通过此设置,全部在我的本地PC上,我看到WCF服务尝试连接到WebApi服务的错误:
{"An attempt was made to access a socket in a way forbidden by its access permissions 127.0.0.1:9102"}
(请注意,使用 WindowsIdentity callerIdentity = WindowsIdentity.GetCurrent();
而不是 WindowsIdentity callerIdentity = ServiceSecurityContext.Current.WindowsIdentity;
工作正常 - 尽管显然这是使用 WCF 用户而不是客户端应用程序用户)
我的问题 - 这是确定 Web API 服务中用户名的最明智方法吗? 甚至有可能这样吗? 如果是这样,知道如何调试"禁止"错误并使此设置正常工作吗?
对于任何感兴趣的人,我设法通过更改以下内容来使其工作。
-
以管理员身份运行这两个服务。 (我相信通过正确的配置,这不是必需的 - 但这足以满足我的目的)
-
确保端口保留 URL 与 WebApi 启动参数中指定的 URL 完全匹配(请参阅:自承载 OWIN 和 urlacl)。就我而言,我对
WebApp.Start(...)
参数使用了以下内容:string baseAddress = "http://+:9100"; StartOptions options = new StartOptions(); options.Urls.Add(baseAddress);
以下是网络:
netsh http add urlacl url=http://+:9111/ user=EVERYONE
在 WCF 服务中,以下行为已添加到服务实现中,我想使用模拟的方法:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
。对于本合同中的其他方法,我需要添加以下内容
[OperationBehavior(Impersonation = ImpersonationOption.NotAllowed)]
我使用"localhost"而不是显式主机名从 WCF 服务引用了 WebApi 服务。 不确定这是否是必需的。
运行 WCF 服务的用户需要具有使用模拟的权限(如果以管理员身份运行,则应已设置)。使用 gpedit.msc;导航到"本地计算机策略"-">计算机配置"-"> Windows 设置"-">安全设置"-">本地策略"-">用户权限分配";确保"身份验证后模拟客户端"包含运行 WCF 服务的用户。 (摘自:https://blogs.technet.microsoft.com/askperf/2007/10/16/wmi-troubleshooting-impersonation-rights/)
最后一步是计算出问题/此答案所需的最小配置集......我想我会把它留到另一天:-)