简体   繁体   English

通过两个Web服务(从WCF到WebApi)从WPF应用程序验证用户

[英]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. 对于任何感兴趣的人,我设法通过更改以下内容来实现此目的。

  1. 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) (我相信使用正确的配置,这不是必需的 - 但这对我的目的来说已经足够了)

  2. 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
  1. 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)]
  1. 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. 不确定这是否是必需的。

  2. 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.

相关问题 如何使用来自WebAPI的域的用户对WebAPI上不同计算机上的客户端进行身份验证? - how can authenticate a client on a different machine on a WebAPI with a user from WebAPI's domain? 如何从Azure Web应用程序与IIS本地托管的WCF服务进行通信? - How to communicate from Azure web app to WCF services hosted locally in IIS? WCF basicHttpBinding与来自WPF应用程序的用户名和密码 - WCF basicHttpBinding with userName and password from a WPF app 从WCF服务验证dotnetnuke - Authenticate dotnetnuke from WCF Service 来自数据库的WCF Web json服务? 读取值错误 - WCF Web json Services from database ? error in Reading value 一个实体共享两个Web服务? - One entity shared across two web services? WCF是由两个Web服务公开的相同类型 - WCF the same type exposed by two web services 跨服务器的WCF服务 - WCF Services across servers WCF RIA SERVICES AuthenticationDomainService 从用户 class 获取附加参数 - WCF RIA SERVICES AuthenticationDomainService get additional parameter from User class 如何从托管在单独服务器上的前端客户端使用 Windows Active Directory 对 .Net Core WebAPI 中的用户进行身份验证? - How to authenticate a user in a .Net Core WebAPI using Windows Active Directory from a frontend client that is hosted on a separate server?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM