wcf配置如下:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior" >
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<serviceCertificate findValue="CN=EdgeCert" x509FindType="FindBySubjectDistinguishedName" storeLocation="LocalMachine" storeName="TrustedPeople"/>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCFSafe.Valid,WCFSafe" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="wsBinding">
<security mode="None">
<message clientCredentialType="UserName" negotiateServiceCredential="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="WCFSafe.Wcf" behaviorConfiguration="ServiceBehavior" >
<endpoint name="service1" binding="wsHttpBinding" bindingConfiguration="wsBinding" contract="WCFSafe.IWcf" >
<identity>
<certificateReference findValue="CN=EdgeCert" x509FindType="FindBySubjectDistinguishedName" storeLocation="LocalMachine" storeName="TrustedPeople"/>
</identity>
</endpoint>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" />
<host>
<baseAddresses>
<add baseAddress="http://127.0.0.1:18883/Wcf" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
negotiateServiceCredential务必设为false,设为true会报错,我找了好久没找到解决方案。
使用cxf生成客户端
cxf下载路径:https://cxf.apache.org/download.html
下载解压后,在bin目录用wsdl2java工具生成客户端
wsdl2java -p com.hand.thirdService -d .\tmp -client http://127.0.0.1:18000/ThirdPartService/OpenService?singleWsdl
-p是包名,-d是文件生成路径
使用keytool导入证书
keytool -import -alias EdgeCert -file D://EdgeCert.cer -keystore D://my.keyStore.jks
-file是证书文件,-keystore是证书库文件,之前没有对应的证书库会生成。
keytool -list -keystore d://my.keyStore.jks
查看是否导入成功。
用eclipse添加项目,并在项目中把cxf/lib的jar包都添加引用(由于不确定哪些jar包是必须的,所以干脆全部添加引用)
将生成的客户端文件导入到项目中。
添加配置文件Client_Encrypt.properties
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=123456
org.apache.ws.security.crypto.merlin.keystore.alias=EdgeCert
org.apache.ws.security.crypto.merlin.file=D://my.keyStore.jks
第1,2行不需要修改,第3行为证书库密码,第4行为导入的证书别名,第5行为证书库路径。
在cxf生成的客户端示例中添加一些内容,如下:
WCF ss = new WCF(wsdlURL, SERVICE_NAME);
IWcf port = ss.getWSHttpBindingIWcf();
Client client = ClientProxy.getClient(port);
Endpoint cxfEndpoint = client.getEndpoint();
Map ctx = ((BindingProvider)port).getRequestContext();
ctx.put("action",WSHandlerConstants.NO_SECURITY);
ctx.put("ws-security.username", "admin");
ctx.put("ws-security.password", "pwd123");
ctx.put("ws-security.encryption.username", "EdgeCert");
ctx.put("ws-security.encryption.properties", "Client_Encrypt.properties");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(ctx);
cxfEndpoint.getOutInterceptors().add(wssOut);
cxfEndpoint.getInInterceptors().add(new LoggingInInterceptor());
cxfEndpoint.getOutInterceptors().add(new LoggingOutInterceptor());
这里需注意,EeCert是证书别名,action别填Username Token,填WSHandlerConstants.NO_SECURITY即可,admin和pwd123是wcf自定义用户名验证里的对应的用户名密码。