浅谈spingmvc 整合CXF +ws-security 实现webservice安全验证
2017-01-17 10:59
561 查看
服务器端搭建
xmlsec-1.5.8.jar
xmlschema-core-2.1.0.jar
woodstox-core-asl-4.4.1.jar
wsdk4j-1.6.3.jar
wss4j–1.6.19.jar
wsdl4j.jar
neethi-3.0.3.jar
saaj.jar
commons-discovery-0.2.jar
commons-logging.jar
stax2-api-3.1.4.jar
jaxrpc.jar
cxf-2.7.18.jar
cxf-rt-ws-security-2.7.18.jar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
使用ws-security进行安全验证,概括来说分两步:
一、创建一个验证类,如本实例的ServerPasswordCallback.class
二、配置WSS4JInInterceptor拦截器,如applicationContext-cxf.xml所示。
三、将applicationContext-cxf.xml配置到web.xml的contextConfigLocation属性中
ServerPasswordCallback.class代码如下:
1
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
该类实现ws-security的CallbackHandler 接口,并重写它的handle方法。该类就是身份验证的主要类,当客户端传过的用户名中为“huwei“时,该方法会将指定的密码告知ws-security的WSPasswordCallback 类,并让它后期去和客户端的密码进行验证,通过就放行,否则打回。在applicationContext-cxf.xml中该类会作为WSS4JInInterceptor拦截器的回调函数属性,进行配置。
以上代码完成了springmvc框架下cxf+ws-security的服务器端配置,以下介绍客户端调用
commons-logging.jar
cxf-2.7.18.jar
cxf-api-2.7.18.jar
cxf-rt-frontend-jaxws-2.7.8.jar
javapns-jdk16-2.2.1.jar
neethi-3.0.3.jar
stax2-api-3.1.4.jar
woodstox-core-asl-4.4.1.jar
wsdl4j-1.6.3.jar
wss4j-1.6.19.jar
xmlschema-core-2.1.0.jar
xmlsec-1.5.8.jar
纯Java调用服务器webservice概括分两步:
一、创建验证辅助类,如本实例的PasswordHandler,用于想客户端传递密码
二、创建调用类,如本实例WsClientTest,进行调用
说明:
同服务端一样,PasswordHandler也是实现了CallbackHandler接口,与服务器端不同的是客户端该类的用途只是为了设置密码,不许要做任何验证。详情见代码
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
QName 指定了调用的命名空间,该命名空间在服务器端的webservice的接口实现类中指定。props为参数传递的容器,是一个指定元素类型的泛型Map对象,设置了
WSHandlerConstants.PASSWORD_TYPE 密码验证类型
WSHandlerConstants.ACTION 验证方式
WSHandlerConstants.USER 用户名
WSHandlerConstants.PW_CALLBACK_CLASS 验证回调函数
等属性,需要着重介绍的是,ws-security 密码验证,客户端并不需要直接将密码字符串作为参数传递给服务端,而是在CallbackHandler的实现类(PasswordHandler )中设置密码,然后将这个PasswordHandler 的类名以参数的形式传递给服务器。服务器端也是,不需要通过get方法获取密码进行比对,而是在验证了用户名通过后,设置指定密码,ws-security框架会自动将服务器端设置的密码和客户端PasswordHandler 传递过的代码做比对,如果而两个密码一致,则放行,否则的话,提示权限验证失败。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
PHP主要是拼接了一个xml,来传递相关验证属性。详见注释。batchAddMailTracks为webservice的具体调用的方法名,使用时,替换成自己的方法即可。基于本人对php不是非常了解,以上代码是从同事运行的代码中考过来,经过验证完全跑的通,期望能为困惑于此的朋友们作为参考。可能有人有困惑命名空间到底该如何设置,我一般是在地址栏中打开webservice调用地址,如本例中的http://192.168.4.35:8080/monitor/ws/wsMailTrack?wsdl,浏览器会显示该webservice 成功调用的xml信息,取到targetNamespace 的值,配置到webservice的实现类中即可
因为本人机器是jdk1.6,所以此次用到的cxf是2.7.18版本的,如果使用cxf3版本的话,jdk必须是1.7及以上,本案例不适用。另外,需要详细学习ws-security且可以FQ的的朋友们,可以上其官网看一下,例子非常的详细http://cxf.apache.org/docs/ws-security.html
cxf+ws-security服务器搭建jar包下载地址:http://download.csdn.net/detail/chrisjingu/9617981
客户端纯java调用代码及jar包下载地址:http://download.csdn.net/detail/chrisjingu/9617995
jar包:
asm-3.3.1.jarxmlsec-1.5.8.jar
xmlschema-core-2.1.0.jar
woodstox-core-asl-4.4.1.jar
wsdk4j-1.6.3.jar
wss4j–1.6.19.jar
wsdl4j.jar
neethi-3.0.3.jar
saaj.jar
commons-discovery-0.2.jar
commons-logging.jar
stax2-api-3.1.4.jar
jaxrpc.jar
cxf-2.7.18.jar
cxf-rt-ws-security-2.7.18.jar
使用cxf搭建webservice
//以下webservice 接口类 @WebService public interface MailTrackWebservice { public int batchAddMailTracks( @WebParam(name = "mailTrackId") String mailTrackId, @WebParam(name="sender")String sender, @WebParam(name="sendDate")String sendDate, @WebParam(name="subject")String subject, @WebParam(name="recipient")String recipient, @WebParam(name="content")String content); } /* 以下是webService 的接口实现类 * @param endpointInterface指定接入点接口:接口必须存在 * @param targetNamespace service 命名空间,一般为域名倒写 * @param serviceName: 对外发布的服务名,指定 Web Service 的服务名 * 称:wsdl:service。缺省值为 Java 类的简单名称 + Service。(字符串) */ @WebService(endpointInterface = "com.monitor.business.webservice.MailTrackWebservice",serviceName="wsMailTrack",targetNamespace="http://webservice.business.monitor.com/") public class MailTrackWebserviceImpl implements MailTrackWebservice { @Autowired private MailTrackService mailTrackService; @Override public int batchAddMailTracks(@WebParam(name = "mailTrackId") String mailTrackId,@WebParam(name = "sender") String sender, @WebParam(name = "sendDate") String sendDate, @WebParam(name = "subject") String subject, @WebParam(name = "recipient") String recipient, @WebParam(name = "content") String content) { MailTrack mt=new MailTrack(); mt.setId(mailTrackId); mt.setSender(sender); mt.setSendDate(sendDate); mt.setContent(content); mt.setRecipient(recipient); mt.setSubject(subject); return mailTrackService.addMailTrack(mt); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
web.xml 配置 cxf servlet 对webservice 进行拦截
<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>
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
创建applicationContext-cxf.xml
在applicationContext.xml同级目录下创建applicationContext-cxf.xml 具体内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:wsa="http://cxf.apache.org/ws/addressing" 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/bindings/soap http://cxf.apache.org/schemas/configuration/soap.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"> <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="wsMailTrackImpl" class="com.monitor.business.webservice.impl.MailTrackWebserviceImpl"></bean> <jaxws:endpoint id="wsMailTrack" implementor="#wsMailTrackImpl" address="/wsMailTrack"> <jaxws:inInterceptors> <!-- WS-Security拦截器 --> <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"> <constructor-arg> <map> <entry key="action" value="UsernameToken"/> <!-- 密码类型,PasswordText表示明文,密文是PasswordDigest --> <entry key="passwordType" value="PasswordText"/> <entry key="passwordCallbackRef"> <!-- 回调函数引用 --> <ref bean="myPasswordCallback"/> </entry> </map> </constructor-arg> </bean> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> </jaxws:inInterceptors> <jaxws:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> </jaxws:outInterceptors> </jaxws:endpoint> <bean class="com.monitor.business.webservice.auth.ServerPasswordCallback" id="myPasswordCallback" /> </beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
使用ws-security进行安全验证,概括来说分两步:
一、创建一个验证类,如本实例的ServerPasswordCallback.class
二、配置WSS4JInInterceptor拦截器,如applicationContext-cxf.xml所示。
三、将applicationContext-cxf.xml配置到web.xml的contextConfigLocation属性中
ServerPasswordCallback.class代码如下:
public class ServerPasswordCallback implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; if ("huwei".equals(pc.getIdentifier())) { pc.setPassword("hello"); } } }
1
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
该类实现ws-security的CallbackHandler 接口,并重写它的handle方法。该类就是身份验证的主要类,当客户端传过的用户名中为“huwei“时,该方法会将指定的密码告知ws-security的WSPasswordCallback 类,并让它后期去和客户端的密码进行验证,通过就放行,否则打回。在applicationContext-cxf.xml中该类会作为WSS4JInInterceptor拦截器的回调函数属性,进行配置。
以上代码完成了springmvc框架下cxf+ws-security的服务器端配置,以下介绍客户端调用
客户端调用
纯java 调用,不使用任何框架
jar包
asm-3.3.jarcommons-logging.jar
cxf-2.7.18.jar
cxf-api-2.7.18.jar
cxf-rt-frontend-jaxws-2.7.8.jar
javapns-jdk16-2.2.1.jar
neethi-3.0.3.jar
stax2-api-3.1.4.jar
woodstox-core-asl-4.4.1.jar
wsdl4j-1.6.3.jar
wss4j-1.6.19.jar
xmlschema-core-2.1.0.jar
xmlsec-1.5.8.jar
纯Java调用服务器webservice概括分两步:
一、创建验证辅助类,如本实例的PasswordHandler,用于想客户端传递密码
二、创建调用类,如本实例WsClientTest,进行调用
说明:
同服务端一样,PasswordHandler也是实现了CallbackHandler接口,与服务器端不同的是客户端该类的用途只是为了设置密码,不许要做任何验证。详情见代码
验证类代码如下
public class PasswordHandler implements CallbackHandler { public void handle(javax.security.auth.callback.Callback[] callbacks) { for (int i = 0; i < callbacks.length; i++) { WSPasswordCallback pc = (WSPasswordCallback)callbacks[i]; pc.setPassword("ftsafe!@#654"); } } }
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
调用类代码如下
public class WsClientTest { /** *<p></p> * @author Z.J * @date 2016-8-25 * @param args void */ public static void main(String[] args) { //这个是用cxf 客户端访问cxf部署的webservice服务 //千万记住,访问cxf的webservice必须加上namespace ,否则通不过 JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); org.apache.cxf.endpoint.Client client = dcf.createClient("http://192.168.4.35:8080/monitor/ws/wsMailTrack?wsdl"); //url为调用webService的wsdl地址 QName name=new QName("http://webservice.business.monitor.com/","batchAddMailTracks"); Map<String, Object> props = new HashMap<String, Object>(); props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); //密码类型 明文:PasswordText密文:PasswordDigest props.put(WSHandlerConstants.PASSWORD_TYPE,WSConstants.PW_TEXT); //用户名 props.put(WSHandlerConstants.USER, "huwei"); //将PasswordHandler 的类名传递给服务器,相当于传递了密码给服务器 props.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordHandler.class.getName()); WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props); client.getOutInterceptors().add(wssOut); //paramvalue为参数值 Object[] objects; try { String mailTrackId=UUID.randomUUID().toString().replace("-", ""); objects = client.invoke(name,mailTrackId,"123@qq.com","2016-09-25","我要发邮件","huwei@ftsafe.com","love you hi"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
QName 指定了调用的命名空间,该命名空间在服务器端的webservice的接口实现类中指定。props为参数传递的容器,是一个指定元素类型的泛型Map对象,设置了
WSHandlerConstants.PASSWORD_TYPE 密码验证类型
WSHandlerConstants.ACTION 验证方式
WSHandlerConstants.USER 用户名
WSHandlerConstants.PW_CALLBACK_CLASS 验证回调函数
等属性,需要着重介绍的是,ws-security 密码验证,客户端并不需要直接将密码字符串作为参数传递给服务端,而是在CallbackHandler的实现类(PasswordHandler )中设置密码,然后将这个PasswordHandler 的类名以参数的形式传递给服务器。服务器端也是,不需要通过get方法获取密码进行比对,而是在验证了用户名通过后,设置指定密码,ws-security框架会自动将服务器端设置的密码和客户端PasswordHandler 传递过的代码做比对,如果而两个密码一致,则放行,否则的话,提示权限验证失败。
PHP调用 java webservice
try{ ini_set('soap.wsdl_cache_enabled','0');//关闭缓存 //webservice 调用地址 $url='http://192.168.4.35:8080/monitor/ws/wsMailTrack?wsdl'; //需要往服务器端传递的参数,这里是我例子中的参数,可忽略 $params = array ( 'mailTrackId'=>$mailTrackId, 'sender'=>$target, 'sendDate'=>date("Y-m-d H:i:s"), 'subject'=>$array['title'], 'recipient'=>$_SERVER['SERVER_ADDR'], 'content'=>$emailContentCode, ); $client= new SoapClient($url); //webservice 命名空间 $nameSpace = "http://webservice.business.monitor.com/"; //这里拼接了一个xml来传递ws-security的一些验证属性 $xml = ' <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <wsse:Username>huwei</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">hello</wsse:Password> </wsse:UsernameToken> </wsse:Security>'; $header = new SoapHeader($nameSpace, 'Security',new SoapVar($xml, XSD_ANYXML), TRUE); $client = new SoapClient($url); $client->__setSoapHeaders(array($header)); $client->__soapCall('batchAddMailTracks', array($params)); }catch(SoapFault $e){ error_log(date("Y-m-d H:i:s").$e->getMessage().PHP_EOL,3,'webservice.log'); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
PHP主要是拼接了一个xml,来传递相关验证属性。详见注释。batchAddMailTracks为webservice的具体调用的方法名,使用时,替换成自己的方法即可。基于本人对php不是非常了解,以上代码是从同事运行的代码中考过来,经过验证完全跑的通,期望能为困惑于此的朋友们作为参考。可能有人有困惑命名空间到底该如何设置,我一般是在地址栏中打开webservice调用地址,如本例中的http://192.168.4.35:8080/monitor/ws/wsMailTrack?wsdl,浏览器会显示该webservice 成功调用的xml信息,取到targetNamespace 的值,配置到webservice的实现类中即可
因为本人机器是jdk1.6,所以此次用到的cxf是2.7.18版本的,如果使用cxf3版本的话,jdk必须是1.7及以上,本案例不适用。另外,需要详细学习ws-security且可以FQ的的朋友们,可以上其官网看一下,例子非常的详细http://cxf.apache.org/docs/ws-security.html
cxf+ws-security服务器搭建jar包下载地址:http://download.csdn.net/detail/chrisjingu/9617981
客户端纯java调用代码及jar包下载地址:http://download.csdn.net/detail/chrisjingu/9617995
相关文章推荐
- 浅谈spingmvc 整合CXF +ws-security 实现webservice安全验证
- CXF 入门:创建一个基于WS-Security标准的安全验证(CXF回调函数使用,)
- CXF 入门:创建一个基于WS-Security标准的安全验证(CXF回调函数使用)(转)
- 用jax-ws来调用cxf webservice接口,jax-ws适应cxf安全验证
- cxf+spring实现ws-security的数字证书验证方式的记录(包括生成证书步骤)
- webservice安全之WS-Security验证
- cxf实现的ws_client(带安全验证)
- webservice之cxf实现[web项目中基于maven与spring整合]
- XFire实现身份验证(基于Xfire SOAP Header的WebService安全验证)
- WebService-CXF和spring整合实现webservice案例(Spring配置注解环境)
- XFire实现身份验证(基于Xfire SOAP Header的WebService安全验证)
- [置顶] spring整合cxf实现webservice发布
- Cxf+wss4j的WS-Security实现【未验证】
- 框架 day64 WebService(注解),CXF框架(jax-ws,Jax-rs,与spring整合)
- cxf整合spring实现webservice
- CXF使用WSS4J实现WS-Security规范之使用用户名令牌
- 构建基于CXF的WebService服务(3)-- 利用拦截器实现权限验证
- 一个简单的WebService实现例子,SOAP安全验证
- 构建基于CXF的WebService服务(3)-- 利用拦截器实现权限验证
- CXF使用WSS4J实现WS-Security规范之使用用户名令牌