分享一下wss4j+cxf基于UsernameToken的安全验证。名词解释:??????
????? cxf???????? : apache下的一个开源项目,用于发布webservice。
????? WSS4J? : Web Services Security for Java.?
废话少说,直接上代码。
??? 1. 首先,需要导入cxf中的所有jar包,及wss4j中的所有jar包与log4j.jar。
????????? (本例中使用的版本是:apache-cxf-2.7.3,wss4j-1.6.9)
??
? 2. 首先建立server 项目,发布一个简单的helloWorldService.?
?
目录结构图:
?
?
??? webservice接口代码:
???
- package?com.wss4j.server;??
- ??
- import?javax.jws.WebParam;??
- import?javax.jws.WebService;??
- ??
- @WebService??
- public?interface?HelloWorld?{??
- ????public?String?sayHello(@WebParam(name?=?"name")?String?name);??
- }??
?webservice实现类
?
?
- package?com.wss4j.server;??
- ??
- ??
- public?class?HelloWorldImpl?implements?HelloWorld?{??
- ??
- ????@Override??
- ????public?String?sayHello(String?name)?{??
- ????????return?"Hello?"?+?name?+?"?^_^?!";??
- ????}??
- ??
- }??
?
?
?接下来是服务端拦截器: ServerPasswordCallback.java
?
- package?com.wss4j.interceptor;??
- ??
- 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.ws.security.WSPasswordCallback;??
- import?org.slf4j.Logger;??
- ??
- public?class?ServerPasswordCallback?implements?CallbackHandler?{??
- ??
- ????private?Logger?logger?=?org.slf4j.LoggerFactory.getLogger(ServerPasswordCallback.class);??
- ??
- ????@Override??
- ????public?void?handle(Callback[]?callbacks)?throws?IOException,??
- ????????????UnsupportedCallbackException?{??
- ????????WSPasswordCallback?pc?=?(WSPasswordCallback)?callbacks[0];??
- ????????//?标识符??
- ????????String?identifier?=?pc.getIdentifier();??
- ????????????????//?此处获取到的password为null,但是并不代表服务端没有拿到该属性。??
- ????????String?password?=?pc.getPassword();??
- ????????logger.info("identifier:"?+?identifier);??
- ????????logger.info("password:"?+?password);??
- ??????????
- ????????if?(identifier?!=?null?&&?identifier.equals("admin"))?{??
- ????????????/**??
- ?????????????*?此处应该这样做:?
- ?????????????????*?1.?查询数据库,得到数据库中该用户名对应密码?
- ?????????????????*?2.?设置密码,wss4j会自动将你设置的密码?与客户端传递的密码进行匹配?
- ?????????????????*?3.?如果相同,则放行,否则返回权限不足信息??
- ?????????????*??
- ?????????????*/??
- ????????????pc.setPassword("password");??
- ????????}else{??
- ????????????logger.info("未授权的用户");??
- ????????}??
- ????}??
- }??
?
?
server-beans.xml
?
- <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/core?http://cxf.apache.org/schemas/core.xsd??
- ????????????????????????http://cxf.apache.org/jaxws??
- ????????????????????????http://cxf.apache.org/schemas/jaxws.xsd">??
- ??
- ????<!--?jar包中自带的cxf文件夹下的*.xml文件?-->??
- ??
- ????<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"?/>??
- ????<bean?id="myPasswordCallback"?class="com.wss4j.interceptor.ServerPasswordCallback"?/>??
- ??
- ????<jaxws:endpoint?id="helloword"?implementor="com.wss4j.server.HelloWorldImpl"??
- ????????address="/helloService">??
- ????????<!--?添加拦截器?-->??
- ????????<jaxws:inInterceptors>??
- ????????????<bean?class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">??
- ????????????????<constructor-arg>??
- ????????????????????<map>??
- ????????????????????????<entry?key="action"?value="UsernameToken"?/>??
- ????????????????????????<entry?key="passwordType"?value="PasswordText"?/>??
- ????????????????????????<entry?key="signaturePropFile"?value="..."?/>??
- ????????????????????????<entry?key="user"?value="FHDServer"?/>??
- ????????????????????????<entry?key="passwordCallbackRef">??
- ????????????????????????????<ref?bean="myPasswordCallback"?/>??
- ????????????????????????</entry>??
- ????????????????????</map>??
- ????????????????</constructor-arg>??
- ????????????</bean>??
- ????????</jaxws:inInterceptors>??
- ????</jaxws:endpoint>??
- ??????
- </beans>??
?
?
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"???
- ????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="../cxf/server-beans.xml"/>??
- </beans>??
?
?
web.xml
?
- <?xml?version="1.0"?encoding="UTF-8"?>??
- <web-app?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"??
- ????xmlns="http://java.sun.com/xml/ns/javaee"?xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"??
- ????xsi:schemaLocation="http://java.sun.com/xml/ns/javaee?http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"??
- ????id="WebApp_ID"?version="3.0">??
- ????<display-name>wss4j001-cxf-server</display-name>??
- ????<welcome-file-list>??
- ????????<welcome-file>index.html</welcome-file>??
- ????????<welcome-file>index.htm</welcome-file>??
- ????????<welcome-file>index.jsp</welcome-file>??
- ????????<welcome-file>default.html</welcome-file>??
- ????????<welcome-file>default.htm</welcome-file>??
- ????????<welcome-file>default.jsp</welcome-file>??
- ????</welcome-file-list>??
- ????<context-param>??
- ????????<param-name>contextConfigLocation</param-name>??
- ????????<param-value>classpath:spring/beans.xml</param-value>??
- ????</context-param>??
- ????<listener>??
- ????????<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>??
- ????</listener>??
- ????<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>/ws/*</url-pattern>??
- ????</servlet-mapping>??
- </web-app>??
?
?
此时,我们的server端就已经搞定了。
?????? 访问链接:http://localhost:8080/wss4j001-cxf-server/ws/helloService?wsdl
即可看到刚刚发布的webservice的wsdl文件。但是不能直接访问方法,因为我们为其增加了安全校验。
?
接下来,创建client 端 项目。
具体项目结构如下:
?
HelloWorldClient.java
?
- package?com.wss4j.client;??
- ??
- import?org.springframework.context.support.ClassPathXmlApplicationContext;??
- ??
- import?com.wss4j.server.HelloWorld;??
- ??
- public?class?HelloWorldClient?{??
- ????public?static?void?main(String[]?args)?{??
- ????????ClassPathXmlApplicationContext?context?=?new?ClassPathXmlApplicationContext(??
- ????????????????new?String[]?{?"cxf/client-beans.xml"?});??
- ????????HelloWorld?client?=?(HelloWorld)?context.getBean("client");??
- ????????String?response?=?client.sayHello("Dan");??
- ????????System.out.println("Response:?"?+?response);??
- ????????System.exit(0);??
- ????}??
- ??
- }??
?
?
?
客户端添加用户认证拦截器 ClientPasswordCallback.java
?
- package?com.wss4j.interceptor;??
- ??
- 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.ws.security.WSPasswordCallback;??
- ??
- public?class?ClientPasswordCallback?implements?CallbackHandler?{??
- ????@Override??
- ????public?void?handle(Callback[]?callbacks)?throws?IOException,??
- ????????????UnsupportedCallbackException?{??
- ????????WSPasswordCallback?pc?=?(WSPasswordCallback)?callbacks[0];??
- ????????String?ident?=?"admin";??
- ????????String?passwd?=?"password";??
- ????????pc.setPassword(passwd);??
- ????????pc.setIdentifier(ident);??
- ??
- ????}??
- }??
?
?
client-beans.xml
?
- <?xml?version="1.0"?encoding="UTF-8"?>??
- <beans?xmlns="http://www.springframework.org/schema/beans"??
- ????xmlns:jaxws="http://cxf.apache.org/jaxws"?xmlns:cxf="http://cxf.apache.org/core"??
- ????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??
- ??????????http://cxf.apache.org/core?http://cxf.apache.org/schemas/core.xsd??
- ??????????http://cxf.apache.org/jaxws???
- ??????????http://cxf.apache.org/schemas/jaxws.xsd">??
- ????<bean?id="clientPasswordCallback"?class="com.wss4j.interceptor.ClientPasswordCallback"?/>??
- ??????
- ????<jaxws:client?id="client"?serviceClass="com.wss4j.server.HelloWorld"??
- ????????address="http://localhost:8080/wss4j001-cxf-server/ws/helloService">??
- ????????<jaxws:outInterceptors>??
- ????????????<bean?class="org.apache.cxf.interceptor.LoggingOutInterceptor"?/>??
- ????????????<bean?class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">??
- ????????????????<constructor-arg>??
- ????????????????????<map>??
- ????????????????????????<entry?key="action"?value="UsernameToken"?/>??
- ????????????????????????<entry?key="passwordType"?value="PasswordText"?/>??
- ????????????????????????<entry?key="user"?value="FHDClient"?/>??
- ????????????????????????<entry?key="passwordCallbackRef">??
- ????????????????????????????<ref?bean="clientPasswordCallback"?/>??
- ????????????????????????</entry>??
- ????????????????????</map>??
- ????????????????</constructor-arg>??
- ????????????</bean>??
- ????????</jaxws:outInterceptors>??
- ????</jaxws:client>??
- ??
- </beans>??
?
?
接下来,我们需要通过wsdl 生成服务端webservice的客户端java文件。这里使用cxf的wsdl2java命令。
?
打开cmd命令行:
????? 1. 进入到 apache-cxf-2.7.3apache-cxf-2.7.3bin 目录下
?????
?????? 2. 执行命令:
?????????????? wsdl2ava? -client http://localhost:8080/wss4j001-cxf-server/ws/helloService?wsdl? ????????
?
???? 3. 生成的java文件就在 apache-cxf-2.7.3apache-cxf-2.7.3bin 目录下,名为com的文件夹。复制文件夹至client项目的src下。
?
?
接下来,首先将server项目添加到服务器中,启动服务器。然后执行 HelloWorldClient.java中的main方法,就可以访问服务端的webservice了,是不是so easy? ^_^ ..