接上例:http://blog.csdn.net/kunshan_shenbin/archive/2008/12/26/3613918.aspx
新建2个批处理文件用以生成服务端及客户端密钥文件。
generateKeyPair.bat
- rem @echo off
- echo alias %1
- echo keypass %2
- echo keystoreName %3
- echo KeyStorePass %4
- echo keyName %5
- echo keyName %5
- keytool -genkey -alias %1 -keypass %2 -keystore %3 -storepass %4 -dname "cn=%1" -keyalg RSA
- keytool -selfcert -alias %1 -keystore %3 -storepass %4 -keypass %2
- keytool -export -alias %1 -file %5 -keystore %3 -storepass %4
generateServerKey.bat
- call generateKeyPair.bat serverAlias aliaspass serverStore.jks keystorePass serverKey.rsa
- call generateKeyPair.bat client-344-839 client344Password clientStore.jks keystorePass clientKey.rsa
- keytool -import -alias serverAlias -file serverKey.rsa -keystore clientStore.jks -storepass keystorePass -noprompt
- keytool -import -alias client-344-839 -file clientKey.rsa -keystore serverStore.jks -storepass keystorePass -noprompt
注意:
生成的密钥文件中包含的信息:
服务端 账户:serverAlias / aliaspass
客户端 账户:client-344-839 / client344Password
依次运行后生成serverStore.jks和clientStore.jks这2个文件待用。
如下图所示建立工程:
所需lib包一览:
XmlSchema-1.4.2.jar
commons-logging-1.1.1.jar
cxf-2.0.9.jar
jaxb-impl-2.0.5.jar
jaxws-api-2.0.jar
neethi-2.0.4.jar
opensaml-1.1.jar
saaj-api-1.3.jar
saaj-impl-1.3.jar
serializer-2.7.1.jar
spring-beans-2.0.8.jar
spring-context-2.0.8.jar
spring-core-2.0.8.jar
spring-web-2.0.8.jar
wsdl4j-1.6.2.jar
wss4j-1.5.4.jar
xalan-2.7.1.jar
xml-resolver-1.2.jar
xmlsec-1.4.0.jar
代码如下:
TestServiceClient.java
- package jp.co.apm.client;
- import jp.co.apm.service.TestService;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class TestServiceClient {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext(
- new String[] { "jp/co/apm/client/clientApplicationContext.xml" });
- TestService service = (TestService) context.getBean("client");
- System.out.println(service.sayHello());
- }
- }
clientApplicationContext.xml
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:jaxws="http://cxf.apache.org/jaxws"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
- <bean id="client" class="jp.co.apm.service.impl.TestServiceImpl" factory-bean="clientFactory" factory-method="create"/>
- <bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
- <property name="serviceClass" value="jp.co.apm.service.TestService">
- </property>
- <property name="address"
- value="http://localhost:8080/APM_CXF/services/test">
- </property>
- <property name="outInterceptors">
- <list>
- <bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
- <ref bean="wss4jOutConfiguration" />
- </list>
- </property>
- </bean>
- <bean id="wss4jOutConfiguration" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
- <property name="properties">
- <map>
- <entry key="action" value="Signature" />
- <entry key="user" value="client-344-839" />
- <entry key="passwordType" value="PasswordDigest" />
- <entry key="signatureKeyIdentifier" value="IssuerSerial" />
- <entry key="signaturePropFile" value="jp/co/apm/client/outsecurity_sign.properties" />
- <entry>
- <key>
- <value>passwordCallbackRef</value>
- </key>
- <ref bean="passwordCallback" />
- </entry>
- </map>
- </property>
- </bean>
- <bean id="passwordCallback" class="jp.co.apm.security.PasswordCallbackHandler"/>
- </beans>
outsecurity_sign.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=keystorePass
- org.apache.ws.security.crypto.merlin.alias.password=client344Password
- org.apache.ws.security.crypto.merlin.keystore.alias=client-344-839
- org.apache.ws.security.crypto.merlin.file=jp/co/apm/client/clientStore.jks
以下是服务端代码:
PasswordCallbackHandler.java
- package jp.co.apm.security;
- import java.io.IOException;
- import java.util.HashMap;
- import java.util.Map;
- import javax.security.auth.callback.Callback;
- import javax.security.auth.callback.CallbackHandler;
- import javax.security.auth.callback.UnsupportedCallbackException;
- import org.apache.ws.security.WSPasswordCallback;
- public class PasswordCallbackHandler implements CallbackHandler {
- private Map<String, String> passwords = new HashMap<String, String>();
- public PasswordCallbackHandler() {
- passwords.put("serveralias", "aliaspass");
- passwords.put("client-344-839", "client344Password");
- }
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
- String id = pc.getIdentifer();
- pc.setPassword((String) passwords.get(id));
- }
- }
TestServiceImpl.java
- package jp.co.apm.service.impl;
- import javax.jws.WebService;
- import jp.co.apm.service.TestService;
- @WebService
- public class TestServiceImpl implements TestService {
- public String sayHello() {
- return "Hello, Shen Bin";
- }
- }
TestService.java
- package jp.co.apm.service;
- import javax.jws.WebService;
- @WebService
- public interface TestService {
- public String sayHello();
- }
server_insecurity_sign.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=keystorePass
- #org.apache.ws.security.crypto.merlin.alias.password=aliaspass
- org.apache.ws.security.crypto.merlin.keystore.alias=serveralias
- org.apache.ws.security.crypto.merlin.file=serverStore.jks
cxf-servlet.xml
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:jaxws="http://cxf.apache.org/jaxws"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
- <import resource="classpath:META-INF/cxf/cxf.xml" />
- <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
- <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
- <jaxws:endpoint id="testservice" implementor="jp.co.apm.service.impl.TestServiceImpl" address="/test">
- <jaxws:features>
- <bean class="org.apache.cxf.feature.LoggingFeature"/>
- </jaxws:features>
- <jaxws:inInterceptors>
- <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/>
- <ref bean="wss4jInConfiguration"/>
- </jaxws:inInterceptors>
- </jaxws:endpoint>
- <bean id="wss4jInConfiguration" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
- <property name="properties">
- <map>
- <entry key="action" value="Signature"/>
- <!--
- <entry key="user" value="client-344-839" />
- <entry key="passwordType" value="PasswordDigest" />
- -->
- <entry key="signaturePropFile" value="server_insecurity_sign.properties"/>
- <entry>
- <key>
- <value>passwordCallbackRef</value>
- </key>
- <ref bean="passwordCallback"/>
- </entry>
- </map>
- </property>
- </bean>
- <bean id="passwordCallback" class="jp.co.apm.security.PasswordCallbackHandler"/>
- </beans>
web.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <display-name>APM</display-name>
- <description>APM</description>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>WEB-INF/cxf-servlet.xml</param-value>
- </context-param>
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
- <servlet>
- <servlet-name>APM</servlet-name>
- <servlet-class>
- org.apache.cxf.transport.servlet.CXFServlet
- </servlet-class>
- <load-on-startup>2</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>APM</servlet-name>
- <url-pattern>/services/*</url-pattern>
- </servlet-mapping>
- <session-config>
- <session-timeout>60</session-timeout>
- </session-config>
- </web-app>
差点忘了一个最重要的环节,就是要在java.security中追加一个解密算法的支持:
/jre/lib/security/java.security文件中,追加类似如下语句:
.....
security.provider.5=sun.security.jgss.SunProvider
security.provider.6=com.sun.security.sasl.Provider
security.provider.7=org.bouncycastle.jce.provider.BouncyCastleProvider