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