• JAX-WS使用Handler实现简单的WebService权限验证


    WebService假设涉及到安全保密或者使用权限的时候,WS-Security一般是最优选择。WS-Security (Web服务安全) 包括了关于怎样在WebService消息上保证完整性和机密性的规约,怎样将签名和加密头加入SOAP消息。只是WS-Security也有一些性能上的损耗,在信息保密要求不是非常高的情况下,能够通过在SOAPHeader中加入简单的校验信息实现。

    详细思路是client调用须要认证的服务时,在SOAPHeader中加入授权信息(如username、password或者序列号等)。服务端收到请求,在SOAPHeader中校验授权信息,校验通过则运行请求,校验不通过则返回错误提示。




    实例代码 http://download.csdn.net/detail/accountwcx/8922191


    client发起请求在SOAPHeader中加入的授权数据格式例如以下

    <auth xmlns="http://www.tmp.com/auth">
    	<name>admin</name>
    	<password>admin</password>
    </auth>


    服务端


    服务端授权校验Handler

    import java.util.Iterator;
    import java.util.Set;
    
    import javax.xml.namespace.QName;
    import javax.xml.soap.SOAPBody;
    import javax.xml.soap.SOAPElement;
    import javax.xml.soap.SOAPEnvelope;
    import javax.xml.soap.SOAPException;
    import javax.xml.soap.SOAPFault;
    import javax.xml.soap.SOAPHeader;
    import javax.xml.soap.SOAPMessage;
    import javax.xml.ws.handler.MessageContext;
    import javax.xml.ws.handler.soap.SOAPHandler;
    import javax.xml.ws.handler.soap.SOAPMessageContext;
    
    /**
     * 服务端请求校验Handler 
     * @author accountwcx@qq.com
     *
     */
    public class ValidateAuthHandler implements SOAPHandler<SOAPMessageContext> {
    
    	@Override
    	public void close(MessageContext context) {
    	}
    
    	@Override
    	public boolean handleFault(SOAPMessageContext context) {
    		return true;
    	}
    
    	@Override
    	public boolean handleMessage(SOAPMessageContext context) {
    		// 推断消息是请求还是响应
    		Boolean output = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);		
    		
    		boolean result = false;
    		
    		SOAPMessage message = context.getMessage();
    		
    		//假设是请求,则运行校验
    		if(!output){
    			result = validate(message);
    			
    			if(!result){
    				validateFail(message);
    			}
    		}
    		
    		System.out.println(output ?

    "服务端响应:" : "服务端接收:"); try { message.writeTo(System.out); } catch (Exception e) { e.printStackTrace(); } System.out.println(" "); return result; } /** * 授权校验失败,在SOAPBody中加入SOAPFault * @param message */ private void validateFail(SOAPMessage message) { try { SOAPEnvelope envelop = message.getSOAPPart().getEnvelope(); envelop.getHeader().detachNode(); envelop.addHeader(); envelop.getBody().detachNode(); SOAPBody body = envelop.addBody(); SOAPFault fault = body.getFault(); if (fault == null) { fault = body.addFault(); } fault.setFaultString("授权校验失败!"); message.saveChanges(); } catch (SOAPException e) { e.printStackTrace(); } } /** * 授权校验 * @param message * @return 校验成功返回true。校验失败返回false */ private boolean validate(SOAPMessage message){ boolean result = false; try { SOAPEnvelope envelop = message.getSOAPPart().getEnvelope(); SOAPHeader header = envelop.getHeader(); if(header != null){ Iterator iterator = header.getChildElements(new QName("http://www.tmp.com/auth", "auth")); SOAPElement auth = null; if(iterator.hasNext()){ //获取auth auth = (SOAPElement)iterator.next(); //获取name Iterator it = auth.getChildElements(new QName("http://www.tmp.com/auth", "name")); SOAPElement name = null; if(it.hasNext()){ name = (SOAPElement)it.next(); } //获取password it = auth.getChildElements(new QName("http://www.tmp.com/auth", "password")); SOAPElement password = null; if(it.hasNext()){ password = (SOAPElement)it.next(); } //推断name和password是否符合要求 if(name != null && password != null && "admin".equals(name.getValue()) && "admin".equals(password.getValue())){ result = true; } } } } catch (SOAPException e) { e.printStackTrace(); } return result; } @Override public Set<QName> getHeaders() { return null; } }



    client


    client加入授权Handler

    import java.util.Set;
    
    import javax.xml.namespace.QName;
    import javax.xml.soap.SOAPElement;
    import javax.xml.soap.SOAPException;
    import javax.xml.soap.SOAPHeader;
    import javax.xml.soap.SOAPMessage;
    import javax.xml.ws.handler.MessageContext;
    import javax.xml.ws.handler.soap.SOAPHandler;
    import javax.xml.ws.handler.soap.SOAPMessageContext;
    
    /**
     * client加入请求授权
     * @author accountwcx@qq.com
     *
     */
    public class AddAuthHandler implements SOAPHandler<SOAPMessageContext> {
    
    	@Override
    	public boolean handleMessage(SOAPMessageContext context) {
    		// 推断消息是请求还是响应
    		Boolean output = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    
    		SOAPMessage message = context.getMessage();
    
    		if (output) {
    			try {
    				SOAPHeader header = message.getSOAPHeader();
    				if (header == null) {
    					header = message.getSOAPPart().getEnvelope().addHeader();
    				}
    
    				SOAPElement auth = header.addChildElement(new QName("http://www.tmp.com/auth", "auth"));
    				
    				SOAPElement name = auth.addChildElement("name");
    				name.addTextNode("admin");
    
    				SOAPElement password = auth.addChildElement("password");
    				password.addTextNode("admin");
    				
    				message.saveChanges();
    
    			} catch (SOAPException e) {
    				e.printStackTrace();
    			}
    		}
    		
    		System.out.println(output ?

    "client请求:" : "client接收:"); try { message.writeTo(System.out); } catch (Exception e) { e.printStackTrace(); } System.out.println(" "); return true; } @Override public boolean handleFault(SOAPMessageContext context) { return true; } @Override public void close(MessageContext context) { } @Override public Set<QName> getHeaders() { return null; } }


    clientHandler配置文件handler-chain.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
    	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    	<javaee:handler-chain>
    		<javaee:handler>
    			<javaee:handler-class>com.rvho.client.handler.AddAuthHandler</javaee:handler-class>
    		</javaee:handler>
    	</javaee:handler-chain>
    </javaee:handler-chains>

    client的Service中加入Handler配置文件

    /**
     * This class was generated by the JAX-WS RI.
     * JAX-WS RI 2.2.9-b130926.1035
     * Generated source version: 2.2
     * 
     */
    @WebServiceClient(name = "HelloWSService", targetNamespace = "http://www.tmp.com/ws/hello", wsdlLocation = "http://localhost:8014/jaxwsserver/services/hello?wsdl")
    @HandlerChain(file="handler-chain.xml")
    public class HelloWSService
        extends Service
    {
    
        private final static URL HELLOWSSERVICE_WSDL_LOCATION;
        private final static WebServiceException HELLOWSSERVICE_EXCEPTION;
        private final static QName HELLOWSSERVICE_QNAME = new QName("http://www.tmp.com/ws/hello", "HelloWSService");
    
        static {
            URL url = null;
            WebServiceException e = null;
            try {
                url = new URL("http://localhost:8014/jaxwsserver/services/hello?wsdl");
            } catch (MalformedURLException ex) {
                e = new WebServiceException(ex);
            }
            HELLOWSSERVICE_WSDL_LOCATION = url;
            HELLOWSSERVICE_EXCEPTION = e;
        }
    
        public HelloWSService() {
            super(__getWsdlLocation(), HELLOWSSERVICE_QNAME);
        }
    
        public HelloWSService(WebServiceFeature... features) {
            super(__getWsdlLocation(), HELLOWSSERVICE_QNAME, features);
        }
    
        public HelloWSService(URL wsdlLocation) {
            super(wsdlLocation, HELLOWSSERVICE_QNAME);
        }
    
        public HelloWSService(URL wsdlLocation, WebServiceFeature... features) {
            super(wsdlLocation, HELLOWSSERVICE_QNAME, features);
        }
    
        public HelloWSService(URL wsdlLocation, QName serviceName) {
            super(wsdlLocation, serviceName);
        }
    
        public HelloWSService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
            super(wsdlLocation, serviceName, features);
        }
    
        /**
         * 
         * @return
         *     returns HelloWS
         */
        @WebEndpoint(name = "HelloWSPort")
        public HelloWS getHelloWSPort() {
            return super.getPort(new QName("http://www.tmp.com/ws/hello", "HelloWSPort"), HelloWS.class);
        }
    
        /**
         * 
         * @param features
         *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
         * @return
         *     returns HelloWS
         */
        @WebEndpoint(name = "HelloWSPort")
        public HelloWS getHelloWSPort(WebServiceFeature... features) {
            return super.getPort(new QName("http://www.tmp.com/ws/hello", "HelloWSPort"), HelloWS.class, features);
        }
    
        private static URL __getWsdlLocation() {
            if (HELLOWSSERVICE_EXCEPTION!= null) {
                throw HELLOWSSERVICE_EXCEPTION;
            }
            return HELLOWSSERVICE_WSDL_LOCATION;
        }
    
    }


    client发起index请求

    URL wsdlUrl = new URL("http://localhost:7180/jaxwsserver/services/hello?wsdl");
    HelloWSService helloWSS = new HelloWSService(wsdlUrl);
    HelloWS helloWS = helloWSS.getHelloWSPort();
    String index = helloWS.index();

    client发起正确授权的请求以及server的响应

    <!-- client请求 -->
    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
    			xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    	<SOAP-ENV:Header>
    		<auth xmlns="http://www.tmp.com/auth">
    			<name>admin</name>
    			<password>admin</password>
    		</auth>
    	</SOAP-ENV:Header>
    	<S:Body>
    		<ns2:index xmlns:ns2="http://www.tmp.com/ws/hello" />
    	</S:Body>
    </S:Envelope>
    
    <!-- 服务端响应 -->
    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
    			xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    	<SOAP-ENV:Header/>
    	<S:Body>
    		<ns2:indexResponse xmlns:ns2="http://www.tmp.com/ws/hello">
    			<return>hello</return>
    		</ns2:indexResponse>
    	</S:Body>
    </S:Envelope>

    client发起错误授权的请求以及server的响应

    <!-- client请求 -->
    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
    			xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    	<SOAP-ENV:Header>
    		<auth xmlns="http://www.tmp.com/auth">
    			<name></name>
    			<password></password>
    		</auth>
    	</SOAP-ENV:Header>
    	<S:Body>
    		<ns2:index xmlns:ns2="http://www.tmp.com/ws/hello" />
    	</S:Body>
    </S:Envelope>
    
    <!-- server响应 -->
    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" 
    			xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    	<S:Header/>
    	<S:Body>
    		<S:Fault>
    			<faultcode>S:Server</faultcode>
    			<faultstring>授权校验失败!</faultstring>
    		</S:Fault>
    	</S:Body>
    </S:Envelope>


    HandlerReolver取代Handler配置文件


    handler-chain配置文件对全部的请求都加入授权验证信息,有些时候不是全部的请求都须要加入授权验证,HandlerResolver提供了在编程时加入Handler的方法,能够用HandlerResolver给须要授权的接口加入Handler。


    URL wsdlUrl = new URL("http://localhost:7180/jaxwsserver/services/hello?

    wsdl"); HelloWSService helloWSS = new HelloWSService(wsdlUrl); //通过HandlerResolver加入Handler helloWSS.setHandlerResolver(new HandlerResolver(){ @Override @SuppressWarnings("rawtypes") public List<Handler> getHandlerChain(PortInfo portInfo) { List<Handler> handlerChain = new ArrayList<Handler>(); handlerChain.add(new AddAuthHandler()); return handlerChain; } }); HelloWS helloWS = helloWSS.getHelloWSPort(); //调用index服务 String index = helloWS.index();



  • 相关阅读:
    2016九大前端必备动画库
    关于页面跳转,登录刷新
    关于换行
    c++ vector 的使用
    c++ namespace的使用
    u盘文件系统故障的修复方法
    nfs的使用
    ubuntu 无声音的解决
    Yii 视图中的 $this
    Apache vhost
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/7389047.html
Copyright © 2020-2023  润新知