cxf webservice接口 实现安全验证

 

   基于 spring + apache cxf

 

1.服务器端 cxf配置:

<?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"

xmlns:jaxrs="http://cxf.apache.org/jaxrs"

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/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">

 

    <import resource="classpath:META-INF/cxf/cxf.xml" />  

    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  

    

<jaxws:endpoint id="greetingService"

implementor="com.test.service.impl.GreetingServiceImpl" 

address="/greetingService" >

<jaxws:inInterceptors>   

            <bean   

                class="org.apache.cxf.interceptor.LoggingInInterceptor" />   

            <bean   

                class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />   

            <bean   

                class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">   

                <constructor-arg>   

                    <map>   

                        <entry key="action" value="UsernameToken" />   

                        <entry key="passwordType"  

                            value="PasswordText" />   

                        <entry key="user" value="cxfUser" />   

                        <entry key="passwordCallbackRef">   

                            <ref bean="serverPasswordCallback" />   

                        </entry>   

                    </map>   

                </constructor-arg>   

            </bean>   

        </jaxws:inInterceptors>   

    </jaxws:endpoint>

<bean id="serverPasswordCallback"  

       class="com.common.cxf.ServerPasswordCallback" />   

</beans> 

说明:

   action:UsernameToken指使用用户令牌 
    passwordType:PasswordText指密码加密策略,这里直接文本 
    user:cxfServer指别名 
    passwordCallBackRef:serverPasswordCallback指消息验证 

 

2.服务器端 CallbackHandler 拦截处理

package com.core.common.cxf;

 

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;

  

  

public class ServerPasswordCallback implements CallbackHandler {   

  

    public void handle(Callback[] callbacks) throws IOException,   

            UnsupportedCallbackException {   

        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];   

        String pw = pc.getPassword();   

        String idf = pc.getIdentifier();   

        System.out.println("password:"+pw);   

        System.out.println("identifier:"+idf);   

        if (idf.equals("admin")) {   

        pc.setPassword("josen");

        } else {   

            throw new SecurityException("验证失败");   

        }   

    }   

  

 

}  

说明:

 

  WSPasswordCallback 的passwordType属性和password 属性都为null,你只能获得用户名(identifier),一般这里的逻辑是使用这个用户名到数据库中查询其密码,然后再设置到password 属性,WSS4J 会自动比较客户端传来的值和你设置的这个值。你可能会问为什么这里CXF 不把客户端提交的密码传入让我们在ServerPasswordCallbackHandler 中比较呢?这是因为客户端提交过来的密码在SOAP 消息中已经被加密为MD5 的字符串,如果我们要在回调方法中作比较,那么第一步要做的就是把服务端准备好的密码加密为MD5 字符串,由于MD5 算法参数不同结果也会有差别,另外,这样的工作CXF 替我们完成不是更简单吗?

 

根据上面说的,我获取的password 为null,所以这里就不用自己判断密码了,只要验证用户名后,在设置密码就可以自动验证了

3.客户端配置文件:

<?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"

xmlns:jaxrs="http://cxf.apache.org/jaxrs"

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/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">

 

  <jaxws:client id="greetingService" serviceClass="com.test.service.GreetingService" 

  address="http://localhost:8080/test/greetingService">

 

          <jaxws:outInterceptors>   

            <bean   

                class="org.apache.cxf.interceptor.LoggingOutInterceptor" />   

            <bean   

                class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />   

            <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="cxfUser" />   

                        <entry key="passwordCallbackRef">   

                            <ref bean="clientPasswordCallback" />   

                        </entry>   

                    </map>   

                </constructor-arg>   

            </bean>   

        </jaxws:outInterceptors> 

    </jaxws:client>   

    <bean id="clientPasswordCallback"  

        class="com.common.cxf.ClientPasswordCallback" />   

 

</beans> 

4.客户端CallbackHandler

package com.common.cxf;

 

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;

  

 

  

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.setPassword("josen");   

             pc.setIdentifier("admin");   

        }   

    }   

  

 

}  

    说明:

  只要两边的 Identifier,Password 相同就ok了

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值