1. 服务端
pom.xml 文件
<!--web service 以下都是cxf必备的 --> <!--org.apache.cxf.transport.servlet.CXFServlet --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>3.1.12</version> </dependency> <!--不加这个包会报错Unable to locate spring NamespaceHandler for XML schemanamespace [http://cxf.apache.org/jaxws] --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.1.12</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-ws-security</artifactId> <version>3.1.12</version> </dependency> <dependency> <groupId>org.apache.wss4j</groupId> <artifactId>wss4j-ws-security-common</artifactId> <version>2.1.10</version> </dependency> <dependency> <groupId>org.apache.wss4j</groupId> <artifactId>wss4j-ws-security-dom</artifactId> <version>2.1.10</version> </dependency>
resources文件
server.properties文件
org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin org.apache.wss4j.crypto.merlin.keystore.type=jks org.apache.wss4j.crypto.merlin.keystore.password=keyStorePassword org.apache.wss4j.crypto.merlin.keystore.file=publicstore.jks
spring-beans.xml文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="helloService" class="com.*.ve.providedinterface.HelloServiceImpl"></bean> <bean id="signatureUser" class="com.*.ve.providedinterface.SignatureUser"> <property name="userMap"> <map> <entry key="ciecc" value="cieccPassword" /> </map> </property> </bean> </beans>
spring-cxf.xml 文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://cxf.apache.org/core" 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 http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"> <bean id="serverPasswordCallback" class="com.*.ve.providedinterface.ServerPasswordCallback"></bean> <!--发布服务 --> <jaxws:endpoint implementor="#helloService" address="/hello"> <jaxws:inInterceptors> <ref bean="wss4jInInterceptor" /> </jaxws:inInterceptors> </jaxws:endpoint> <cxf:bus> <cxf:features> <cxf:logging /> </cxf:features> </cxf:bus> <bean id="wss4jInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"> <constructor-arg> <map> <entry key="action" value="Signature Encrypt" /> <!-- 提供公钥的密码 --> <entry key="passwordCallbackRef" value-ref="serverPasswordCallback" /> <entry key="signatureVerificationPropFile" value="server.properties" /> <entry key="decryptionPropFile" value="server.properties" /> </map> </constructor-arg> </bean> </beans>
Shiro.properties文件
/webserver/** =anon \n\
HelloService.java文件
package com.*.ve.providedinterface; import javax.jws.WebParam; import javax.jws.WebService; @WebService public interface HelloService { String say(@WebParam(name = "name") String name); public String getSubjects(); }
HelloServiceImpl.java
package com.*.ve.providedinterface; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.annotation.Resource; import javax.jws.WebService; import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.*.ve.entity.common.LessonGroup; import com.*.ve.service.LessonGroupService; @Component @WebService(endpointInterface = "com.*.ve.providedinterface.HelloService",targetNamespace="http://providedinterface.ve.*.com/") public class HelloServiceImpl implements HelloService { @Resource private LessonGroupService lessonGroupService; public String say(String name) { return "hello " + name; } public static String object2str(Object obj){ String retStr = ""; ObjectMapper mapper = new ObjectMapper(); try { retStr = mapper.writeValueAsString(obj); } catch (JsonProcessingException e) { e.printStackTrace(); } return retStr; } @Override public String getSubjects() { List<LessonGroup> subjects=(List<LessonGroup>) lessonGroupService.findAll(); List<ProvideSubjectData> datas=new ArrayList<ProvideSubjectData>(); for (Iterator iterator = subjects.iterator(); iterator.hasNext();) { LessonGroup lessonGroup = (LessonGroup) iterator.next(); ProvideSubjectData data=new ProvideSubjectData(); data.setEnable(lessonGroup.getEnable()); data.setIsShow(lessonGroup.getIsShow()); data.setName(lessonGroup.getName()); data.setSubjecttype_id(lessonGroup.getIdStr()); datas.add(data); } return JsonOperator.toJson(datas); } }
JsonOperator.java文件
package com.*.ve.providedinterface; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class JsonOperator { /** * 将java对象转换成json字符串 */ public static <T> T json2Bean(String jsonString, Class<T> cls) { T t = null; try { Gson gson = new Gson(); t = gson.fromJson(jsonString, cls); } catch (Exception e) { e.printStackTrace(); } return t; } /** * 将对象转换成json数据 * * @param o * @return */ public static <T> String toJson(Object o) { Gson gson = new Gson(); // Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); String jsonStr = gson.toJson(o); return jsonStr; } /** * 将json数据转换成List列表返回 * * @param jsonString * @param type * @return */ public static <T> List<T> json2List(String jsonString, Type type) { List<T> list = new ArrayList<T>(); try { Gson gson = new Gson(); list = gson.fromJson(jsonString, type); } catch (Exception e) { } return list; } }
ProvideSubjectData.java文件
package com.*.ve.providedinterface; public class ProvideSubjectData { private String name; private Boolean enable; private String subjecttype_id; private Boolean isShow; public String getName() { return name; } public void setName(Stringname) { this.name =name; } public Boolean getEnable() { return enable; } public void setEnable(Booleanenable) { this.enable =enable; } public String getSubjecttype_id() { return subjecttype_id; } public void setSubjecttype_id(Stringsubjecttype_id) { this.subjecttype_id =subjecttype_id; } public Boolean getIsShow() { return isShow; } public void setIsShow(BooleanisShow) { this.isShow =isShow; } }
ServerPasswordCallback.java文件
package com.*.ve.providedinterface; 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.wss4j.common.ext.WSPasswordCallback; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * 提供了两个用户:server和client,用户名和密码都放在userMap中,这里需要将JDK提供的javax.security.auth. * callback.Callback转型为WSS4J提供的org.apache.wss4j.common.ext.WSPasswordCallback, * 在handle方法中实现对客户端密码的验证,最终需要将密码放入到callback对象中 * * @author zdh * */ @Component public class ServerPasswordCallback implements CallbackHandler { @Autowired private SignatureUser user; public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback callback = (WSPasswordCallback) callbacks[0]; String clientUsername = callback.getIdentifier(); String serverPassword = user.getUserMap().get(clientUsername); if (serverPassword != null) { callback.setPassword(serverPassword); } } }
SignatureUser.java文件
package com.*.ve.providedinterface; import org.springframework.stereotype.Component; import java.util.Map; @Component public class SignatureUser { private Map<String, String> userMap; public Map<String, String> getUserMap() { return userMap; } public void setUserMap(Map<String, String> userMap) { this.userMap = userMap; } }
web.xml文件
<servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/webserver/*</url-pattern> </servlet-mapping>
启动服务器
使用jdk工具
wsimport -s . -encoding utf-8 http://localhost:8080/webserver/hello?wsdl 生成客户端代码
客户端(pom.xml 和服务端相同)
Client.java文件
package com.*.ve.providedinterface; import java.util.Iterator; import java.util.List; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; public class Client { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring-client.xml"); HelloService service = context.getBean("helloService", HelloService.class); String result = service.say("world"); String subjects=service.getSubjects(); System.out.println(result); System.out.println(subjects); List<ProvideSubjectData> provideSubjectDatas = null; ObjectMapper mapper = new ObjectMapper(); try { provideSubjectDatas = mapper.readValue(subjects, new TypeReference<List<ProvideSubjectData>>() {}); if(provideSubjectDatas!=null && provideSubjectDatas.size()>0){ for (Iterator iterator = provideSubjectDatas.iterator(); iterator.hasNext();) { ProvideSubjectData provideSubjectData = (ProvideSubjectData) iterator.next(); System.out.println(provideSubjectData.getName()+" "+provideSubjectData.getIsShow()); } } } catch (Exception e) { e.printStackTrace(); } //js 请求服务端的数据 } }
ClientPasswordCallback.java文件
package com.*.ve.providedinterface; import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.wss4j.common.ext.WSPasswordCallback; import org.springframework.stereotype.Component; @Component public class ClientPasswordCallback implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback callback = (WSPasswordCallback) callbacks[0]; callback.setPassword("cieccPassword"); //key 的密码 } }
JsonOperator.java文件
package com.*.ve.providedinterface; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class JsonOperator { /** * 将java对象转换成json字符串 */ public static <T> T json2Bean(String jsonString, Class<T> cls) { T t = null; try { Gson gson = new Gson(); t = gson.fromJson(jsonString, cls); } catch (Exception e) { e.printStackTrace(); } return t; } /** * 将对象转换成json数据 * * @param o * @return */ public static <T> String toJson(Object o) { Gson gson = new Gson(); // Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); String jsonStr = gson.toJson(o); return jsonStr; } /** * 将json数据转换成List列表返回 * * @param jsonString * @param type * @return */ public static <T> List<T> json2List(String jsonString, Type type) { List<T> list = new ArrayList<T>(); try { Gson gson = new Gson(); list = gson.fromJson(jsonString, type); } catch (Exception e) { } return list; } }
ProvideSubjectData.java文件
package com.*.ve.providedinterface; public class ProvideSubjectData { private String name; private Boolean enable; private String subjecttype_id; private Boolean isShow; public String getName() { return name; } public void setName(Stringname) { this.name =name; } public Boolean getEnable() { return enable; } public void setEnable(Booleanenable) { this.enable =enable; } public ProvideSubjectData() { super(); } public String getSubjecttype_id() { return subjecttype_id; } public void setSubjecttype_id(Stringsubjecttype_id) { this.subjecttype_id =subjecttype_id; } public Boolean getIsShow() { return isShow; } public void setIsShow(BooleanisShow) { this.isShow =isShow; } }
3.公钥私钥生成
keytool -genkey -alias ciecc -keypass cieccPassword -keyalg RSA -keysize 1024 -validity 3650 -keystore privatestore.jks -storepass keyStorePassword -dname "cn=ciecc" keytool -selfcert -alias ciecc -keystore privatestore.jks -storepass keyStorePassword -keypass cieccPassword keytool -importkeystore -alias ciecc -deststorepass keyStorePassword -destkeypass cieccPassword -destkeystore publicstore.jks -srckeystore privatestore.jks -srcstorepass keyStorePassword