跨两个 Web 服务(从 WCF 到 WebApi)从 WPF 应用程序验证用户
Authenticate user from WPF app across two web services (from WCF to WebApi)
我有以下情况:
WPF client application -> WCF Service -> WebApi Service
我希望能够在 WebApi 服务中验证客户端应用程序的用户。我不需要完整的 impersonation/delegation - 我只需要客户的登录 ID,因为我正在使用第三方授权系统的用户 ID。 WCF 服务和 Web Api 服务都在同一台服务器上。
我目前正在尝试的方法是模拟 WindowsIdentity,如下所示。
1.使用 Owin
自托管的 WebApi 服务
WebApp.Start(options,
builder =>
{
// Authenticate POST requests, but not GET requests
// Adapted from:
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 上,我看到尝试连接到 WebApi 服务的 WCF 服务出错:
{"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 服务中确定用户名的最明智的方法吗?这甚至可能吗?如果是这样,知道如何调试 "forbidden" 错误并使此设置正常工作吗?
对于任何感兴趣的人,我设法通过更改以下内容来实现它。
运行 两者都以管理员身份提供服务。 (我相信如果配置正确,这不是必需的 - 但这对我的目的来说已经足够了)
确保端口预留 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;导航到本地计算机策略 -> 计算机配置 -> Windows 设置 -> 安全设置 -> 本地策略 -> 用户权限分配;确保 "Impersonate a client after authentication" 包含您作为 运行 WCF 服务的用户。 (摘自:https://blogs.technet.microsoft.com/askperf/2007/10/16/wmi-troubleshooting-impersonation-rights/)
最后一步是计算出问题/这个答案所需的最小配置集……我想我会把它留到另一天:-)
我有以下情况:
WPF client application -> WCF Service -> WebApi Service
我希望能够在 WebApi 服务中验证客户端应用程序的用户。我不需要完整的 impersonation/delegation - 我只需要客户的登录 ID,因为我正在使用第三方授权系统的用户 ID。 WCF 服务和 Web Api 服务都在同一台服务器上。
我目前正在尝试的方法是模拟 WindowsIdentity,如下所示。
1.使用 Owin
自托管的 WebApi 服务 WebApp.Start(options,
builder =>
{
// Authenticate POST requests, but not GET requests
// Adapted from:
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 上,我看到尝试连接到 WebApi 服务的 WCF 服务出错:
{"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 服务中确定用户名的最明智的方法吗?这甚至可能吗?如果是这样,知道如何调试 "forbidden" 错误并使此设置正常工作吗?
对于任何感兴趣的人,我设法通过更改以下内容来实现它。
运行 两者都以管理员身份提供服务。 (我相信如果配置正确,这不是必需的 - 但这对我的目的来说已经足够了)
确保端口预留 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;导航到本地计算机策略 -> 计算机配置 -> Windows 设置 -> 安全设置 -> 本地策略 -> 用户权限分配;确保 "Impersonate a client after authentication" 包含您作为 运行 WCF 服务的用户。 (摘自:https://blogs.technet.microsoft.com/askperf/2007/10/16/wmi-troubleshooting-impersonation-rights/)
最后一步是计算出问题/这个答案所需的最小配置集……我想我会把它留到另一天:-)