[英]Authenticate user from WPF app across two web services (from WCF to WebApi)
I have the following situation: 我有以下情况:
WPF client application -> WCF Service -> WebApi Service
I want to be able to authenticate the user of the client application when in the WebApi service. 我希望能够在WebApi服务中验证客户端应用程序的用户。 I do not require full impersonation/delegation - all I require is the client's login ID, as I am using the user ID for a third party authorisation system.
我不需要完全模拟/委派 - 我要求的只是客户端的登录ID,因为我使用的是第三方授权系统的用户ID。 Both WCF Service and Web Api Service are on the same server.
WCF服务和Web Api服务都在同一台服务器上。
The current approach I am trying is Impersonation of the WindowsIdentity, as follows. 我正在尝试的当前方法是模仿WindowsIdentity,如下所示。
1. WebApi service self-hosted with Owin 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 Service 2. WCF服务
In <system.web>
: <authentication mode="Windows" />
在
<system.web>
: <authentication mode="Windows" />
In <bindings>
: 在
<bindings>
:
<binding name="BasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
In the code for the specific function I want to impersonate: 在我想模仿的特定函数的代码中:
WindowsIdentity callerIdentity = ServiceSecurityContext.Current.WindowsIdentity;
using (callerIdentity.Impersonate())
{
var request = ...;
request.ImpersonationLevel = TokenImpersonationLevel.Impersonation;
request.UseDefaultCredentials = true;
// Use request to call Web Api
}
3. In the client: 3.在客户端:
<endpointBehaviors>
<behavior name="ImpersonationBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
With this set-up, all on my local PC, I see an error from the WCF service trying to connect to the WebApi service: 通过这个设置,所有在我的本地PC上,我看到WCF服务尝试连接到WebApi服务时出错:
{"An attempt was made to access a socket in a way forbidden by its access permissions 127.0.0.1:9102"}
(Note that using WindowsIdentity callerIdentity = WindowsIdentity.GetCurrent();
instead of WindowsIdentity callerIdentity = ServiceSecurityContext.Current.WindowsIdentity;
works fine - although obviously this is using the WCF user rather than then client app user) (请注意,使用
WindowsIdentity callerIdentity = WindowsIdentity.GetCurrent();
而不是WindowsIdentity callerIdentity = ServiceSecurityContext.Current.WindowsIdentity;
工作正常 - 尽管显然这是使用WCF用户而不是客户端应用程序用户)
My question - is this the most sensible way of determining the user name in the Web Api service? 我的问题 - 这是在Web Api服务中确定用户名的最明智的方法吗? Is it even possible like this?
甚至可能这样吗? If so, any idea how to debug the "forbidden" error and get this set-up working?
如果是这样,任何想法如何调试“禁止”错误并使这个设置工作?
For anyone interested, I managed to get this working by changing the following. 对于任何感兴趣的人,我设法通过更改以下内容来实现此目的。
Run both services as Administrator. 以管理员身份运行两项服务 (I believe that with the right configuration, this wouldn't be required - but this is good enough for my purposes)
(我相信使用正确的配置,这不是必需的 - 但这对我的目的来说已经足够了)
Ensure the port reservation URL exactly matches the URL specified in the WebApi start-up parameters (See: Self hosted OWIN and urlacl ). 确保端口保留URL与WebApi启动参数中指定的URL完全匹配(请参阅: 自托管OWIN和urlacl )。 In my case I used the following for
WebApp.Start(...)
parameter: 在我的例子中,我使用以下
WebApp.Start(...)
参数:
string baseAddress = "http://+:9100"; StartOptions options = new StartOptions(); options.Urls.Add(baseAddress);
And the following for the netsh: 以下为netsh:
netsh http add urlacl url=http://+:9111/ user=EVERYONE
In the WCF service, the following behaviour was added to the method in the service implementation that I wanted to use impersonation: 在WCF服务中,以下行为被添加到我想要使用模拟的服务实现中的方法:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
...and for other methods in this contract, I needed to add the following ......对于本合同中的其他方法,我需要添加以下内容
[OperationBehavior(Impersonation = ImpersonationOption.NotAllowed)]
I referenced the WebApi service from the WCF service using "localhost" rather than an explicit hostname. 我使用“localhost”而不是显式主机名从WCF服务引用了WebApi服务。 Not sure whether this is required.
不确定这是否是必需的。
The user running the WCF service needs to have permissions to use Impersonation (should already be set up if running as Administrator). 运行WCF服务的用户需要具有使用模拟的权限(如果以管理员身份运行,则应该已设置)。 Use gpedit.msc;
使用gpedit.msc; navigate to Local Computer Policy -> Computer Configuration -> Windows Settings -> Security Settings -> Local Policies -> User Rights Assignment;
导航到本地计算机策略 - >计算机配置 - > Windows设置 - >安全设置 - >本地策略 - >用户权限分配; ensure "Impersonate a client after authentication" contains the user that you run the WCF service as.
确保“身份验证后模拟客户端”包含您运行WCF服务的用户。 (Taken from: https://blogs.technet.microsoft.com/askperf/2007/10/16/wmi-troubleshooting-impersonation-rights/ )
(摘自: https : //blogs.technet.microsoft.com/askperf/2007/10/16/wmi-troubleshooting-impersonation-rights/ )
The final step would be to work out the minimal set of configuration required from both the question / this answer ... I think I'll leave that for another day :-) 最后一步是从问题/这个答案中找出所需的最小配置......我想我会留下另一天:-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.