首页 > 解决方案 > 带有 Windows 身份验证的 WCF 服务不会拒绝不受信任的用户

问题描述

我正在 WPF 应用程序和 Windows 服务 throw WCF 之间开发“自动连接”模式。我想只允许受信任的域用户连接到特定的 WCF 服务,而不需要 Windows 凭据(用户已经登录了他的 Windows 会话)。该服务接下来会将用户登录到应用程序。

我创建了一个 WCF 服务,其安全模式为 «Transport»,Transport.ClientCredentialType 为 «Windows»(客户端和服务器上的绑定相同)。在同一应用程序中运行其他 WCF 服务,安全模式设置为“无”。

当我在 LocalService 帐户下的域机器上运行 windows 服务,并在域用户帐户下的另一台机器上运行客户端时,我可以在 OperationContext 对象中获取服务器端的用户 Windows 身份 « DOMAIN\user »。我看到使用了 Kerberos,并且我认为存在某种模拟,这没关系。

但是,当我在不知道域用户的工作组机器(域外)上运行 Windows 服务时,OperationContext WindowsIdentity 设置为« MACHINE_NAME\Administrator »(在服务器上创建的本地会话)。服务调用没有错误,也没有异常,我不知道为什么。WindowsIdentity 对象的 IsAuthenticated 属性始终设置为 true。

我已经用“消息”的安全模式进行了测试。

我想知道是否有可能告诉 WCF 拒绝所有未经真正身份验证的连接?

更新:这里有一些可能有帮助的信息:

 public static TClient Create<TClient, TChannel>(params IContractBehavior[] behaviors)
          where TChannel : class
          where TClient : ClientBase<TChannel>
        {
            var typeOfClient = typeof(TClient);
            var ctor = typeOfClient.GetConstructor(new[] { _bindingType, _endpointAddressType });
            if (ctor == null)
            {
                throw new Exception($"{typeOfClient} has no constructor taking 2 parameters ({_bindingType},{_endpointAddressType})");
            }
            var address = getClientBaseEndPointAddress(typeof(TChannel));
            var binding = getBinding<TClient>(address.Uri.Scheme);
            var clt = (TClient)ctor.Invoke(new object[] { binding, address });
            foreach (var behavior in behaviors)
            {
                clt.ChannelFactory.Endpoint.Contract.Behaviors.Add(behavior);
            }
            manageDataContractResolver<TClient, TChannel>(clt);
            clt.setOperationTimeout(binding.SendTimeout);
            return clt;
        }
   var ret = new NetTcpBinding
   {
      MaxBufferSize = bc.MessageSize,
      MaxBufferPoolSize = bc.MessageSize,
      ...        
   };

   // Secured or not
   if (secured)
   {
      ret.Name = "Default_Secured_Binding";
      ret.Security.Mode = SecurityMode.Transport;
      ret.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;      
    }
    else
    {
       ret.Security.Mode = SecurityMode.None;
       ret.Name = "Default_Binding";
    }

我认为 WCF 会拒绝任何未经完全身份验证的请求,但我无法收到任何“身份验证错误”。

如果您需要更多信息,请与我们联系。

标签: windowswcfauthentication

解决方案


如果客户端没有提供windows凭据作为客户端windows凭据,则将使用当前计算机用户的凭据进行身份验证。认证的条件是这个凭证可以登录到服务器(windows用户)
客户端如何调用服务、客户端代理类或ChannelFactory?这是在客户端设置凭据的方法。

ServiceReference2.Service1Client client = new ServiceReference2.Service1Client();
            //if we don't set up this, The computer user credentials that are currently running the program will be sent to the server.
            client.ClientCredentials.Windows.ClientCredential.UserName = "administrator";
            client.ClientCredentials.Windows.ClientCredential.Password = "123456";

前提是服务器端配置如下,

  <system.serviceModel>
    <services>
      <service name="WcfService1.Service1">
        <endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1" bindingConfiguration="mybinding">
        </endpoint>
        <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"></endpoint>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="mybinding">
          <security mode="Transport">
            <transport clientCredentialType="Windows"></transport>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

请发布您完整的服务器配置和客户端配置(system.servicecmodel部分)以供调用,我会尝试定位问题。
如果有什么我可以帮忙的,请随时告诉我。


推荐阅读