2011-01-26 79 views
4

我有一个WCF服务,托管在IIS中。在服务上,我有大约20种服务方法。我想用这些用户名/密码来保护其中的一些方法。我无法控制调用该服务的客户端,因此我无法在客户端上安装证书。我们的服务充当平台,持有所有用户资料信息,包括登录信息。没有客户端证书的WCF消息/方法安全

我认为,我想客户端验证一次到身份验证(用户名,密码)方法对WCF服务,获得授权令牌回来,并传递令牌的后续调用。 (有些像Asp.net会员提供者使用表单认证会话)。如果可能的话,我不希望客户端必须为每个方法调用传递用户名/密码。这是正确的模式吗?有没有更好的方式使这个功能使用标准的WCF功能?有没有人有任何示例配置/代码来显示正确的方式来实现它的工作?

回答

4

WCF不按操作验证提供开箱即用。如果您需要安全和不安全的操作,最简单的方法是将它们分成两个服务合同,并将每个安全设置公开。

您授权令牌的想法是在WCF已实施,但在你的情况下,你必须使用的wsHttpBinding,用户名客户端凭据,SecurityContext的服务证书。

<system.serviceModel> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="securedService"> 
      <serviceCredentials> 
      <serviceCertificate x509FindType="FindBySubjectName" findValue="ServerCert" 
           storeLocation="LocalMachine" storeName="My"/> 
      </serviceCredentials> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
     <wsHttpBinding> 
     <binding name="Secured"> 
      <security mode="Message"> 
      <message clientCredentialType="UserName" establishSecurityContext="true" /> 
      </security> 
     </binding> 
     </wsHttpBinding> 
    </bindings> 
    <services> 
     <service name="MessageSecurity.Service" behaviorConfiguration="securedService"> 
     <endpoint address="" binding="wsHttpBinding" bindingConfiguration="Secured" 
        contract="MessageSecurity.IService"> 
     </endpoint> 
     </service> 
    </services> 
    </system.serviceModel> 

SecurityContext是基于WS-SecureConversation的可互操作功能。它只需要在来自服务代理实例的第一次调用中传递用户名和密码(在WCF中,这是完全透明的 - 客户端代理实例维护安全上下文)。以下呼叫仅使用首次呼叫期间发出的安全令牌。 SecurityContext在wsHttpBinding中默认打开。

这种结构也将进行加密和签名的消息 - 这是全功率的WS-Security。任何其他方法都取决于你。你必须自己完全实现它。

您提到您无法控制客户端。这并不意味着你不能使用证书。如果您使用证书,则客户有责任在他们想要致电您的服务时获得该证书。它与控制客户关于证书的信任无关 - 对于公共Web服务,它意味着从可信任的证书颁发机构购买证书。

此外,可以在不安装服务证书的情况下获得服务证书。第一种可能性是使用证书作为端点身份。在这种情况下,编码的证书是WSDL的一部分:

<wsdl:service name="Service"> 
    <wsdl:port name="WSHttpBinding_IService" binding="tns:WSHttpBinding_IService"> 
    <soap12:address location="http://localhost:1432/Service.svc" /> 
    <wsa10:EndpointReference> 
     <wsa10:Address>http://localhost:1432/Service.svc</wsa10:Address> 
     <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity"> 
     <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> 
      <X509Data> 
      <X509Certificate>MIICmzCCAYegAwI....<X509Certificate> 
      </X509Data> 
     </KeyInfo> 
     </Identity> 
    </wsa10:EndpointReference> 
    </wsdl:port> 
</wsdl:service> 

如果指定与配置服务证书的wsHttpBinding终点,你不设置其身份这是自动完成的。这种方法的缺点是证书到期。如果更改过期证书,则必须更新所有客户端。

第二种可能性是使服务凭据谈判:

<bindings> 
    <wsHttpBinding> 
    <binding name="Secured"> 
     <security mode="Message"> 
     <message clientCredentialType="UserName" negotiateServiceCredential="true"/> 
     </security> 
    </binding> 
    </wsHttpBinding> 
</bindings> 

协商默认情况下开启。它使用TLSNego协议在安全通信开始之前交换服务凭证(证书)。这种方法的缺点是TLSNego不被所有平台支持。

+1

我可以用`netTCPBinding`来做到这一点吗? – Sreekumar 2012-06-29 06:23:35

1

FYI:如果你想使用内置的WCF自定义用户名/密码子系统,WCF 4.0中引入的一个Allow Insecure Transport property。这允许您在没有证书等的情况下使用WCF安全子系统......这在您认为即使WCF认为消息仍然安全的情况下也很有用(例如,在设备级别完成SSL而不是一个网络服务器级别,或者当使用IP过滤时)。

相关问题