我有以下情况:
WPF client application -> WCF Service -> WebApi Service
我希望能够在WebApi服务中验证客户端应用程序的用户。我不需要完全模拟/委派 - 我要求的只是客户端的登录ID,因为我使用的是第三方授权系统的用户ID。 WCF服务和Web Api服务都在同一台服务器上。
我正在尝试的当前方法是模仿WindowsIdentity,如下所示。
1。使用Owin自行托管的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。 WCF服务
<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服务中确定用户名的最明智的方法吗?甚至可能这样吗?如果是这样,任何想法如何调试“禁止”错误并使这个设置工作?
答案 0 :(得分:0)
对于任何有兴趣的人,我设法通过更改以下内容来实现这一目标。
以管理员身份运行这两项服务。 (我相信使用正确的配置,这不是必需的 - 但这对我的目的来说已经足够了)
确保端口保留URL与WebApi启动参数中指定的URL完全匹配(请参阅:Self hosted OWIN and urlacl)。就我而言,我使用以下WebApp.Start(...)
参数:
string baseAddress = "http://+:9100";
StartOptions options = new StartOptions();
options.Urls.Add(baseAddress);
以下为netsh:
netsh http add urlacl url=http://+:9111/ user=EVERYONE
在WCF服务中,我想要使用模拟的服务实现中的方法添加了以下行为:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
...对于本合同中的其他方法,我需要添加以下内容
[OperationBehavior(Impersonation = ImpersonationOption.NotAllowed)]
我使用“localhost”而不是显式主机名从WCF服务引用了WebApi服务。不确定是否需要这样做。
运行WCF服务的用户需要具有使用模拟的权限(如果以管理员身份运行,则应该已设置)。使用gpedit.msc;导航到本地计算机策略 - &gt;计算机配置 - &gt; Windows设置 - &gt;安全设置 - &gt;本地政策 - &gt;用户权利分配;确保“身份验证后模拟客户端”包含您运行WCF服务的用户。 (摘自:https://blogs.technet.microsoft.com/askperf/2007/10/16/wmi-troubleshooting-impersonation-rights/)
最后一步是从问题/这个答案中找出所需的最小配置......我想我会留下另一天: - )