zoukankan      html  css  js  c++  java
  • 带有WS-Security验证的webservice

    示例用的是spring+CXF来配置webservice

    首先是web.xml配置,将spring,CXF的配置文件加载进去,由于我客户端跟服务端在同一个工程里面,所以配置文件在一块。

        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/classes/spring-cxf.xml,<!--服务端用到的配置-->
                /WEB-INF/classes/spring-cxf-client.xml<!--客户端用到的配置文件-->
            </param-value>
        </context-param>    
        <servlet>
            <servlet-name>cxf-jeeek</servlet-name>
            <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>cxf-jeeek</servlet-name>
            <url-pattern>/services/*</url-pattern>
        </servlet-mapping>

    一、服务端

      <1>CXF的配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:p="http://www.springframework.org/schema/p" 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-3.0.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" />
        <import resource="classpath:/META-INF/cxf/cxf-extension-soap.xml" />
        <!--配置拦截器,用来验证Token信息-->
        <bean id="exampleServiceInterceptor" class="com.ekservice.interceptor.ExampleServiceInterceptor">
        </bean>
        
        <bean id="exampleServiceImpl" class="com.ekservice.impl.ExampleServiceImpl" />
        <jaxws:endpoint implementor="#exampleServiceImpl" address="/ExampleService">
            <!--  -->
            <jaxws:inInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
                 <!-- 这个地方不知道为什么,官方文档说CXF2.0.x需要加这个过滤器,但是我用的是CXF2.7.7不加SAAJInInterceptor过滤器报错 -->
                <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
                <bean id="WSS4JInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
                    <constructor-arg>
                        <map>
                            <entry key="action" value="UsernameToken"></entry>
                            <entry key="passwordType" value="PasswordText"></entry>
                            <!-- 设置密码类型为加密
                            <entry key="passwordType" value="PasswordDigest" />-->
    
                            <entry key="passwordCallbackClass" value="com.ekservice.interceptor.ExampleServiceInterceptor"></entry>
                        </map>
                    </constructor-arg>
                </bean>
            </jaxws:inInterceptors>
    
            <jaxws:outInterceptors>
                <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
            </jaxws:outInterceptors>
        </jaxws:endpoint>
        
    </beans>

        <2>拦截器ExampleServiceInterceptor.java的代码,有详细注释

    package com.ekservice.interceptor;
    
    import org.apache.log4j.Logger;
    import org.apache.ws.security.WSPasswordCallback;
    import org.apache.ws.security.WSSecurityException;
    
    import javax.security.auth.callback.Callback;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.callback.UnsupportedCallbackException;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    /** 
     * @author EK
     * @version 创建时间:2015-5-14 下午04:13:47 
     * 类说明 
     */
    public class ExampleServiceInterceptor implements CallbackHandler{
        Logger logger = Logger.getLogger(ExampleServiceInterceptor.class);
    
        private Map<String, String> passwords = new HashMap<String, String>();
        
        public ExampleServiceInterceptor() {
            passwords.put("admin", "password");
        }
        public void handle(Callback[] callbacks) throws IOException,
                UnsupportedCallbackException {
            
            for (int i = 0; i < callbacks.length; i++) {
                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
                String identifier = pc.getIdentifier();
                int usage = pc.getUsage();
                logger.info("Client Token [username: " + identifier+", password: "+ passwords.get(identifier) + "] Exist user: "+passwords.containsKey(identifier));
                if (usage == WSPasswordCallback.USERNAME_TOKEN) {// 密钥方式USERNAME_TOKEN
                    if (!passwords.containsKey(identifier)) {
                        try {
                            throw new WSSecurityException("User not match - "+identifier);
                        } catch (WSSecurityException e) {
                            e.printStackTrace();
                        }
                    }
                    // username token pwd...
                    // ▲这里的值必须和客户端设的值相同,从cxf2.4.x后校验方式改为cxf内部实现校验,不必自己比较password是否相同
                    // 请参考:http://cxf.apache.org/docs/24-migration-guide.html的Runtime
                    // Changes片段
                    pc.setPassword(passwords.get(identifier));// ▲【这里非常重要】▲
                    // ▲PS 如果和客户端不同将抛出org.apache.ws.security.WSSecurityException:
                    // The
                    // security token could not be authenticated or
                    // authorized异常,服务端会认为客户端为非法调用
                }else if (usage == WSPasswordCallback.SIGNATURE) {// 密钥方式SIGNATURE
                    if (!passwords.containsKey(identifier)) {
                        try {
                            throw new WSSecurityException("User not match - "+identifier);
                        } catch (WSSecurityException e) {
                            e.printStackTrace();
                        }
                    }
                    // set the password for client's keystore.keyPassword
                    // ▲这里的值必须和客户端设的值相同,从cxf2.4.x后校验方式改为cxf内部实现校验,不必自己比较password是否相同;
                    // 请参考:http://cxf.apache.org/docs/24-migration-guide.html的Runtime
                    // Changes片段
                    pc.setPassword(passwords.get(identifier));// //▲【这里非常重要】▲
                    // ▲PS:如果和客户端不同将抛出org.apache.ws.security.WSSecurityException:The
                    // security token could not be authenticated or
                    // authorized异常,服务端会认为客户端为非法调用
                }
            }
        }
    
    }

          <3>接口及其实现类的代码,比较简单,只是做个示例

    package com.ekservice.service;
    
    import com.ek.entry.user.User;
    
    import javax.jws.WebMethod;
    import javax.jws.WebParam;
    import javax.jws.WebResult;
    import javax.jws.WebService;
    
    /** 
     * @author EK
     * @version 创建时间:2015-5-14 下午02:17:59 
     * 类说明 
     */
    @WebService(targetNamespace="http://jeeek-dp/", name="ExampleService")
    public interface ExampleService {
    
        @WebResult(name="password")
        @WebMethod(action="http://jeeek-dp/ExampleService/getStr")
        public User getStr(@WebParam(name="name")String userName);
    
    
        @WebMethod(action="http://jeeek-dp/ExampleService/receive")
        public void receive();
    
        @WebResult(name="tokenId")
        @WebMethod(action="http://jeeek-dp/ExampleService/getTokenId")
        public String getTokenId();
    
        @WebResult(name="sendUnitInfo")
        @WebMethod(action="http://jeeek-dp/ExampleService/getSendUnitInfo")
        public int getSendUnitInfo(@WebParam(name="orgAccountId")long orgAccountId, @WebParam(name="recOrgType")int recOrgType, @WebParam(name="recOrgId")long recOrgId);
    
    }
    package com.ekservice.impl;
    
    import com.ek.entry.user.User;
    import com.ekservice.service.ExampleService;
    import org.apache.log4j.Logger;
    
    import javax.jws.WebService;
    
    /** 
     * @author EK
     * @version 创建时间:2015-5-14 下午02:30:35 
     * 类说明 
     */
    @WebService(targetNamespace="http://jeeek-dp/", serviceName="ExampleService", name="ExampleService")
    public class ExampleServiceImpl implements ExampleService {
        Logger logger = Logger.getLogger(ExampleServiceImpl.class);
    
        public User getStr(String userName) {
            User user = new User();
            user.setAddress("北京市海淀区222号");
            user.setMobilePhone("010-1101111");
            
            System.out.println(userName+" "+user.getAddress());
            
            return user;
        }
    
    
        @Override
        public void receive() {
            this.logger.info("Call reveive() method....");
        }
    
        @Override
        public String getTokenId() {
            this.logger.info("Call getTokenId() method....");
            return "success";
        }
    
        @Override
        public int getSendUnitInfo(long orgAccountId, int recOrgType, long recOrgId) {
            this.logger.info("Call getSendUnitInfo() method...."+orgAccountId+", "+recOrgType+", "+recOrgId);
            return 0;
        }
    
    
    }

    二、客户端

        <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"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans   
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
            http://cxf.apache.org/jaxws   
            http://cxf.apache.org/schemas/jaxws.xsd">
    
        <bean id="exampleServiceClientInterceptor" 
            class="com.ek.client.interceptor.ExampleServiceClientInterceptor"></bean>
        <bean id="WSS4JOutInterceptor" 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="admin" />
                    <!-- <entry key="mustUnderstand" value="false"></entry> -->
                    <entry key="passwordCallbackRef">
                        <ref bean="exampleServiceClientInterceptor" />
                    </entry>
                </map>
            </constructor-arg>
        </bean>
        <jaxws:client id="exampleService"  
            address="http://localhost:8080/jeeek-dp/services/ExampleService"
            serviceClass="com.ek.client.services.example.ExampleService">
            <jaxws:outInterceptors>  
                <bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor"></bean>
                <ref bean="WSS4JOutInterceptor"/>
            </jaxws:outInterceptors>
        </jaxws:client>
        
        <bean id="eperpServiceClientInterceptor" 
            class="com.ek.client.interceptor.CPERPServiceClientInterceptor"></bean>
        <bean id="cperp" 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="cpweb" />
                    <entry key="passwordCallbackRef">
                        <ref bean="eperpServiceClientInterceptor" />
                    </entry>
                </map>
            </constructor-arg>
        </bean>
        
    </beans>

        <2>客户端拦截器代码

    package com.ek.client.interceptor;
    
    import org.apache.log4j.Logger;
    import org.apache.ws.security.WSPasswordCallback;
    import org.apache.ws.security.WSSecurityException;
    
    import javax.security.auth.callback.Callback;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.callback.UnsupportedCallbackException;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    /** 
     * @author EK
     * @version 创建时间:2015年5月15日 上午11:36:20 
     * 类说明 
     */
    public class ExampleServiceClientInterceptor implements CallbackHandler{
    
        Logger logger = Logger.getLogger(ExampleServiceClientInterceptor.class);
    
        private Map<String, String> passwords = new HashMap<String, String>();
        
        public ExampleServiceClientInterceptor() {
            passwords.put("admin", "password");
        }
        public void handle(Callback[] callbacks) throws IOException,
                UnsupportedCallbackException {
            
            for (int i = 0; i < callbacks.length; i++) {
                WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
                String identifier = pc.getIdentifier();
                int usage = pc.getUsage();
                
                if (usage == WSPasswordCallback.USERNAME_TOKEN) {// 密钥方式USERNAME_TOKEN
                    logger.info("Client Token [username: " + identifier+", password: "+ passwords.get(identifier) + "] Exist user= "+passwords.containsKey(identifier));
                    if (!passwords.containsKey(identifier)) {
                        try {
                            throw new WSSecurityException("User not match - "+identifier);
                        } catch (WSSecurityException e) {
                            e.printStackTrace();
                        }
                    }
                    pc.setPassword(passwords.get(identifier));// //▲【这里非常重要】▲
                }else if (usage == WSPasswordCallback.SIGNATURE) {// 密钥方式SIGNATURE
                    if (!passwords.containsKey(identifier)) {
                        try {
                            throw new WSSecurityException("User not match - "+identifier);
                        } catch (WSSecurityException e) {
                            e.printStackTrace();
                        }
                    }
                    pc.setPassword(passwords.get(identifier));// //▲【这里非常重要】▲
                }
            }
        }
    
    }

        <3>客户端接口代码

    package com.ek.client.services.example;
    
    import javax.jws.WebMethod;
    import javax.jws.WebParam;
    import javax.jws.WebResult;
    import javax.jws.WebService;
    import javax.xml.ws.RequestWrapper;
    import javax.xml.ws.ResponseWrapper;
    
    /**
     * 
     */
    @WebService(targetNamespace = "http://jeeek-dp/", name = "ExampleService")
    public interface ExampleService {
    
        @WebResult(name = "password", targetNamespace = "")
        @RequestWrapper(localName = "getStr", targetNamespace = "http://jeeek-dp/")
        @WebMethod(action = "http://jeeek-dp/ExampleService/getStr")
        @ResponseWrapper(localName = "getStrResponse", targetNamespace = "http://jeeek-dp/")
        public User getStr(
            @WebParam(name = "name", targetNamespace = "")
            java.lang.String name
        );
    
        
        @RequestWrapper(localName = "receive", targetNamespace = "http://jeeek-dp/")
        @WebMethod(action = "http://jeeek-dp/ExampleService/receive")
        public void receive();
    
        @WebResult(name = "tokenId", targetNamespace = "")
        @RequestWrapper(localName = "getTokenId", targetNamespace = "http://jeeek-dp/")
        @WebMethod(action = "http://jeeek-dp/ExampleService/getTokenId")
        @ResponseWrapper(localName = "getTokenIdResponse", targetNamespace = "http://jeeek-dp/")
        public java.lang.String getTokenId();
    
        @WebResult(name = "sendUnitInfo", targetNamespace = "")
        @RequestWrapper(localName = "getSendUnitInfo", targetNamespace = "http://jeeek-dp/")
        @WebMethod(action = "http://jeeek-dp/ExampleService/getSendUnitInfo")
        @ResponseWrapper(localName = "getSendUnitInfoResponse", targetNamespace = "http://jeeek-dp/")
        public java.lang.Integer getSendUnitInfo(
                @WebParam(name = "orgAccountId", targetNamespace = "")
                java.lang.Long orgAccountId,
                @WebParam(name = "recOrgType", targetNamespace = "")
                java.lang.Integer recOrgType,
                @WebParam(name = "recOrgId", targetNamespace = "")
                java.lang.Long recOrgId
        );
    
    }

         <4>客户端调用类

    package com.ek.client.call;
    
    import com.ek.client.interceptor.ExampleServiceClientInterceptor;
    import com.ek.client.services.example.ExampleService;
    import com.ek.client.services.example.User;
    import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
    import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
    import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
    import org.apache.ws.security.WSConstants;
    import org.apache.ws.security.handler.WSHandlerConstants;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /** 
     * @author EK
     * @version 创建时间:2015年5月15日 上午11:05:06 
     * 类说明 
     */
    public class ExampleServiceClient {
    
        public static void main(String[] args) {
    //        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-cxf-client.xml");
    //        ExampleService es = (ExampleService) ctx.getBean("exampleService");
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
            map.put(WSHandlerConstants.USER, "admin");
            map.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
            map.put(WSHandlerConstants.PW_CALLBACK_CLASS, ExampleServiceClientInterceptor.class.getName());
            
            List list = new ArrayList();
            list.add(new SAAJOutInterceptor());
            list.add(new WSS4JOutInterceptor(map));
            
            JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
            factory.setServiceClass(ExampleService.class);
            factory.setAddress("http://localhost:8080/jeeek-dp/services/ExampleService");
            factory.getOutInterceptors().addAll(list);
            ExampleService es = (ExampleService) factory.create();
            
            User u = es.getStr("ssss");
            //Integer sui = es.getSendUnitInfo(1L, 2, 3L);
            String tokenId = es.getTokenId();
            //es.receive();
    
            
            System.out.println("的, " + tokenId);
            //System.out.println("的" + sui);
        }
    }
  • 相关阅读:
    POJ 1426 Find The Multiple(数论——中国同余定理)
    POJ 2253 Frogger(Dijkstra变形——最短路径最大权值)
    POJ 3790 最短路径问题(Dijkstra变形——最短路径双重最小权值)
    POJ 3278 Catch That Cow(模板——BFS)
    HDU 1071 The area
    HDU 1213 How Many Tables(模板——并查集)
    POJ 1611 The Suspects
    light oj 1214 Large Division
    POJ 1258 Agri-Net(Prim算法求解MST)
    POJ 2387 Til the Cows Come Home(模板——Dijkstra算法)
  • 原文地址:https://www.cnblogs.com/edi-kai/p/6549353.html
Copyright © 2011-2022 走看看