CXF涉及安全方面主要有三个途径:
- 最简单的方式是使用Http Basic Auth,就是WSS4J的UsernameToken实现方式,优点是简单易用,缺点是每次都会在MESSAGE里面传密码,安全性低。
- Transport level(传输层内)的实现Https。CXF samples里面有一个例子wsdl_first_https, 很详细的讲了怎么使用。
- 对MESSAGE进行加密和签名(encryption and signing),请参考官方教程。
先来看第一种实现方式,按照上一篇教程中的内容先配置好,然后根据下面顺序进行修改
1. 修改服务端spring配置文件
<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-servlet.xml" /> <bean id="serverPasswordCallback" class="com.demo.cxf.callbacks.ServerPasswordCallback"></bean> <bean id="serverWSS4JInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"> <constructor-arg> <map> <entry key="action" value="UsernameToken Timestamp" /> <!-- MD5加密明文密码 --> <entry key="passwordType" value="PasswordDigest" /> <entry key="passwordCallbackRef"> <ref bean="serverPasswordCallback" /> </entry> </map> </constructor-arg> </bean> <jaxws:endpoint id="helloWorld" implementor="com.demo.cxf.helloword.impl.HelloWordImpl" address="/HelloWorld"> <jaxws:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" /> <ref bean="serverWSS4JInInterceptor"/> </jaxws:inInterceptors> <jaxws:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> </jaxws:outInterceptors> <jaxws:properties> <entry key="mtom-enabled" value="true" /> </jaxws:properties> </jaxws:endpoint> </beans>
2. 创建服务端CallbackHandler
package com.demo.cxf.callbacks; 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 ServerPasswordCallback implements CallbackHandler { Map<String, String> user = new HashMap<String, String>(); { user.put("admin", "123"); user.put("su", "123"); } @Override public void handle(Callback[] callbacks) throws IOException,UnsupportedCallbackException { WSPasswordCallback wpc = (WSPasswordCallback) callbacks[0]; if (!user.containsKey(wpc.getIdentifier())) { throw new SecurityException("No Permission!"); } /* * 此处特别注意:: * WSPasswordCallback 的passwordType属性和password 属性都为null, * 你只能获得用户名(identifier), * 一般这里的逻辑是使用这个用户名到数据库中查询其密码, * 然后再设置到password 属性,WSS4J 会自动比较客户端传来的值和你设置的这个值。 * 你可能会问为什么这里CXF 不把客户端提交的密码传入让我们在ServerPasswordCallbackHandler 中比较呢? * 这是因为客户端提交过来的密码在SOAP 消息中已经被加密为MD5 的字符串, * 如果我们要在回调方法中作比较,那么第一步要做的就是把服务端准备好的密码加密为MD5 字符串, * 由于MD5 算法参数不同结果也会有差别,另外,这样的工作CXF 替我们完成不是更简单吗? */ wpc.setPassword(user.get(wpc.getIdentifier()));//如果包含用户名,就设置该用户名正确密码,由CXF验证密码 String username = wpc.getIdentifier(); String password = wpc.getPassword(); System.out.println("userName:" + username + " password:" + password); } }
3. 修改客户端spring配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:jaxws="http://cxf.apache.org/jaxws" 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/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <bean id="clientOutPasswordCallback" class="cxf.callbacks.ClientOutPasswordCallback"></bean> <bean id="clientWSS4JOutInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor"> <constructor-arg> <map> <entry key="action" value="UsernameToken Timestamp" /> <!-- MD5加密明文密码 --> <entry key="passwordType" value="PasswordDigest" /> <entry key="user" value="admin" /> <entry key="passwordCallbackRef"> <ref bean="clientOutPasswordCallback" /> </entry> </map> </constructor-arg> </bean> <jaxws:client id="helloClient" serviceClass="com.demo.cxf.helloword.HelloWord" address="http://localhost:8080/webservice/services/HelloWorld"> <jaxws:outInterceptors> <ref bean="clientWSS4JOutInterceptor"/> </jaxws:outInterceptors> </jaxws:client> </beans>
4. 创建客户端CallbackHandler
package cxf.callbacks; 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 ClientOutPasswordCallback implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { if (callbacks != null && callbacks.length > 0) { Callback callback = callbacks[0]; // 设置用户密码,供服务端验证,可以从配置文件或者数据库里面读取 WSPasswordCallback wsc = (WSPasswordCallback) callback; wsc.setPassword("123"); } } }
5. 调用代码
ApplicationContext context = new ClassPathXmlApplicationContext( "cxf/cxf-client.xml"); HelloWord helloWord = (HelloWord) context.getBean("helloClient"); System.out.println(helloWord.sayHello("Bruce"));
相关推荐
NULL 博文链接:https://wangwengcn.iteye.com/blog/1881535
NULL 博文链接:https://wangwengcn.iteye.com/blog/1880018
TipTec.Developing.Web.Services.with.Apache.CXF.and.Axis2.Jan.2010.rar
PacktPub.Apache.CXF.Web.Service.Development.Dec.2009.rar
org.apache.cxf.spring.remoting.Jsr181HandlerMapping.jar
apache-cxf-2.4.6.zip
02.CXF功能概述_CXF发展历史和使用CXF开发WebService服务器端
08.CXF拦截器的理论以及如何为CXF的客户端和服务器端添加拦截器
java通过cxf实现webservice所需jar包。java通过cxf实现webservice所需jar包。
利用Apache CXF开发webservice接口需要用到的jar集合 cxf-core-3.0.15.jar cxf-rt-bindings-soap-3.0.15.jar cxf-rt-bindings-xml-3.0.15.jar cxf-rt-databinding-jaxb-3.0.15.jar cxf-rt-frontend-jaxws-3.0.15.jar...
CXF文档已经 所依赖的jar全部在里面
s.addLocation(StaxUtils.java:1038) at org.apache.cxf.staxutils.StaxUtils.startElement(StaxUtils.java:893) at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:965) at org.apache.cxf....
14.CXF与Spring整合的第二种方式_让JavaEE应用依赖第三方WebService
cxf-2.1.jar cxf-2.1.jar cxf-2.1.jar cxf-2.1.jar
12.CXF与Spring整合为JavaEE应用发布WebService
Apache CXF = Celtix + XFire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-...Apache CXF已经是一个正式的Apache顶级项目。