加入参数传递及安全机制
一、 WebService服务端:
1) 在WebService_CXF1的基础上添加以下包:
2) 添加以下类:
JavaBean对象:
————————UserBean—————————
public class UserBean {
private StringuserID;
private StringuserName;
public String getUserID() {
returnuserID;
}
public void setUserID(String userID) {
this.userID = userID;
}
public String getUserName() {
returnuserName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
————————ListBean—————————
public class ListBean {
privateListlist;
publicListgetList() {
returnlist;
}
public void setList(Listlist) {
this.list = list;
}
}
Service层:
————————UserService—————————
@WebService
public interface UserService{
public UserBeangetUser(UserBean u);
public ListBeangetUserList();
}
————————UserServiceImpl—————————
public class UserServiceImpl implements UserService{
/**
* u -> 接收客户端传的对象
* dto -> 回传给客户端对象
*/
public UserBeangetUser(UserBean u) {
System.out.println("-- " + u.getUserID() +" - " + u.getUserName());
UserBean dto =new UserBean();
dto.setUserID("serverUserID1");
dto.setUserName("serverUserName1");
return dto;
}
/**
* obj -> 回传给客户端对象
*/
public ListBeangetUserList() {
Listlist = newArrayList();
for(int i = 0; i < 5;i++){
UserBeanbean =new UserBean();
bean.setUserID("serverUserId" + i);
bean.setUserName("serverUserName" + i);
list.add(bean);
}
ListBean listBean=new ListBean();
listBean.setList(list);
return listBean;
}
}
————————ServerPasswordCallback—————————
/**
* 访问WebService时进行口令验证
* 消息验证类通过实现CallbackHandler接口,实现handle方法来进行用户认证
*/
public class ServerPasswordCallback implements CallbackHandler {
publicvoid handle(Callback[] callbacks)throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback)callbacks[0];
String userId = pc.getIdentifier();//获取用户名
String passWord = pc.getPassword();
System.out.println("-- " + userId +" -" + passWord);
if("admin".equals(userId)){
pc.setPassword("1");//设置密码
System.out.println("-------success!");
}else{
thrownew SecurityException("fail");
}
}
}
————————applicationContext-cxf.xml—————————
<jaxws:endpoint id="userService"address="/cxfTest"
implementor="com.mei.service.UserServiceImpl">
<jaxws:inInterceptors>
<beanclass="org.apache.cxf.interceptor.LoggingInInterceptor"/>
<beanclass="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/>
<beanclass="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entrykey="action"value="UsernameToken"/>
<entrykey="passwordType"value="PasswordDigest"/>
<entrykey="user"value="cxfServer"/>
<entrykey="passwordCallbackRef">
<refbean="serverPasswordCallback"/>
</entry>
</map>
</constructor-arg>
</bean>
</jaxws:inInterceptors>
</jaxws:endpoint>
<beanid="serverPasswordCallback"class="com.mei.util.ServerPasswordCallback"/>
————————web.xml—————————
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
Classpath:web/applicationContext-cxf.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
二、 WebService客户端:
1) 添加以下类:
同服务端相同的JavaBean对象(UserBean、ListBean),以及Service层的接口UserService
————————UserController—————————
try{
ApplicationContext context = new ClassPathXmlApplicationContext("web/applicationContext-cxf.xml");
UserService service = (UserService)context.getBean("userService");
UserBean u = new UserBean();
u.setUserID("clientUserId1");
u.setUserName("clientUserName1");
UserBean dto = service.getUser(u);
System.out.println("-- " + dto.getUserID() +" - " + dto.getUserName());
System.out.println("----------------------------------");
ListBean listBean = service.getUserList();
List list = listBean.getList();
for(int i = 0; i < list.size(); i++){
UserBean u1 = (UserBean)list.get(i);
System.out.println("-- " + u1.getUserID() +" - " + u1.getUserName());
}
}catch(Exception e){
e.printStackTrace();
}
————————ClientPasswordCallback—————————
public class ClientPasswordCallback implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for(int i = 0; i < callbacks.length; i++){
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
pc.setIdentifier("admin");
pc.setPassword("1");
}
}
}
————————applicationContext-cxf.xml—————————
<jaxws:client id="userService" address="http://服务端IP/WebServiceCFX/services/cxfTest"
serviceClass="com.mei.service.UserService">
<jaxws:outInterceptors>
<beanclass="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
<beanclass="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor"/>
<beanclass="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<!-- 设置加密类型 -->
<entrykey="action"value="UsernameToken"/>
<!-- 设置密码类型为密文 -->
<entrykey="passwordType"value="PasswordDigest"/>
<entrykey="user"value="cxfClient"/>
<entrykey="passwordCallbackRef">
<refbean="clientPasswordCallback"/>
</entry>
</map>
</constructor-arg>
</bean>
</jaxws:outInterceptors>
</jaxws:client>
<beanid="clientPasswordCallback"class="com.mei.util.ClientPasswordCallback"/>
加密方式PasswordDigest/PasswordText,指客户端在发送消息的时候,使用明文/密文进行加密
-------------------------------------------------------------------------------------------------------------------------------------------------------
Caused by:org.apache.cxf.binding.soap.SoapFault: The security token could not beauthenticated or authorized
报错原因:1、客户端/服务器端使用的加密方式不同
2、密码不一致