zoukankan      html  css  js  c++  java
  • Web Service学习-CXF开发Web Service的权限控制(二)


    Web Service怎样进行权限控制?

     

    解决思路:server端要求input消息总是携带实username。password信息,假设没实username和password信息。直接拒绝调用

     

    解决方式:拦截器

     

    为了让程序猿能訪问,并改动CXF框架所生成的SOAP消息,CXF提供了拦截器

     

    CXF(Celtix +XFire)说明:

     

    假设不用CXF等框架,SOAP消息的生成。解析都是由程序猿负责。不管是加入username。password信息还是提取username,password信息,都可由程序猿代码完毕。

    假设使用CXF等框架,SOAP消息的生成,解析都是由CXF等框架来完毕。

     

    总的来说,CXF公布WebService进行了封装,简化了我们的操作。

     

    拦截器:


    服务端加入拦截器:


    1,获取Endpointpublish的方法返回值。

    2,调用该对象的getInInterceptors,getOutInterceptors方法来获取InOut拦截器列表,接下来就能够加入拦截器了


    package com.tgb.client;
    
    
    import javax.xml.ws.Endpoint;
    
    import org.apache.cxf.interceptor.LoggingInInterceptor;
    import org.apache.cxf.interceptor.LoggingOutInterceptor;
    import org.apache.cxf.jaxws.EndpointImpl;
    
    import com.tgb.service.HelloWorld;
    import com.tgb.service.impl.HelloWorldImpl;
    
    public class ServerMain {
    
    	public static void main(String[] args){
    		
    		HelloWorld hw=new HelloWorldImpl();
    		//调用endpoint的publish方法。来公布web service
    //		Endpoint.publish("http://192.168.24.215:8889/hjy",hw);
    		EndpointImpl ep=(EndpointImpl)Endpoint.publish("http://192.168.24.215:8899/hjy",hw);
    		
    		//加入In拦截器
    		ep.getInInterceptors().add(new LoggingInInterceptor());
    		//加入Out拦截器
    		ep.getOutInterceptors().add(new LoggingOutInterceptor());
    		
    		System.out.println("Web Service暴露成功");
    	}
    }

    输出内容:




    客户端加入拦截器:

     

    1,加入对应的CXFjar

    2,调用ClientProxy的getClient方法,调用该方法以远程Web Service的代理为參数

    3,调用Client对象的getInInterceptors。getOutInterceptors方法来获取InOut拦截器列表,接下来就能够加入拦截器了


    package hjy;
    
    import java.util.List;
    
    import org.apache.cxf.endpoint.Client;
    import org.apache.cxf.frontend.ClientProxy;
    import org.apache.cxf.interceptor.LoggingInInterceptor;
    import org.apache.cxf.interceptor.LoggingOutInterceptor;
    
    import com.tgb.service.Cat;
    import com.tgb.service.HelloWorld;
    import com.tgb.service.User;
    import com.tgb.service.impl.HelloWorldImpl;
    
    public class ClientMain {
    
    	public static void main(String[] args){
    		HelloWorldImpl factory=new HelloWorldImpl();
    		//此处返回的仅仅是远程Web Service的代理
    		HelloWorld hw=factory.getHelloWorldImplPort();
    		
    		Client client=ClientProxy.getClient(hw);
    		client.getInInterceptors().add(new LoggingInInterceptor());
    		client.getOutInterceptors().add(new LoggingOutInterceptor());
    		
    		System.out.println(hw.sayHi("hejingyuan"));
    		
    		System.out.println("--------------------------");
    		
    		User user=new User();
    		user.setId(20);
    		user.setName("孙悟空");
    		user.setPass("111");
    		user.setAddress("花果山");
    		
    		List<Cat> cats=hw.getCatsByUser(user);
    		for(Cat cat:cats){
    			System.out.println(cat.getName());
    		}
    		
    		System.out.println("--------------------------");
    		
    		System.out.println(hw.getAllCats().getEntry().get(0).getKey());
    		System.out.println(hw.getAllCats().getEntry().get(0).getValue().getName());
    		
    		
    
    	}
    }
     

    打印内容为:




    自己定义拦截器

     

    实现效果:当输入usernamepassword时。才干够调用我们的服务。

    即我们须要在服务端加入输入拦截,在客户端加入输出拦截

    自己定义拦截器,须要实现Interceptor接口,实际上,我们通常会继承AbstractPhaseInterceptor

     

    服务端代码:


    package com.tgb.client;
    
    
    import javax.xml.ws.Endpoint;
    
    import org.apache.cxf.interceptor.LoggingInInterceptor;
    import org.apache.cxf.interceptor.LoggingOutInterceptor;
    import org.apache.cxf.jaxws.EndpointImpl;
    
    import com.tgb.auth.AuthInterceptor;
    import com.tgb.service.HelloWorld;
    import com.tgb.service.impl.HelloWorldImpl;
    
    public class ServerMain {
    
    	public static void main(String[] args){
    		
    		HelloWorld hw=new HelloWorldImpl();
    		//调用endpoint的publish方法,来公布web service
    //		Endpoint.publish("http://192.168.24.215:8889/hjy",hw);
    		EndpointImpl ep=(EndpointImpl)Endpoint.publish("http://192.168.24.215:8891/hjy",hw);
    		
    		//加入In拦截器,该AuthInterceptor就会负责检查username。password是否正确
    		ep.getInInterceptors().add(new AuthInterceptor());
    		//加入Out拦截器
    //		ep.getOutInterceptors().add(new LoggingOutInterceptor());
    		
    		System.out.println("Web Service暴露成功");
    	}
    }
    

    AuthInterceptor :


    package com.tgb.auth;
    
    import java.util.List;
    
    import org.apache.cxf.binding.soap.SoapMessage;
    import org.apache.cxf.headers.Header;
    import org.apache.cxf.interceptor.Fault;
    import org.apache.cxf.phase.AbstractPhaseInterceptor;
    import org.apache.cxf.phase.Phase;
    import org.w3c.dom.Element;
    import org.w3c.dom.NodeList;
    
    
    //通过PhaseInterceptor,能够指定拦截器在哪个阶段起作用
    public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
    
    	//因为AbstractPhaseInterceptor无无參数构造器,使用继承的方式,须要显示调用父类有參数的构造器
    	public AuthInterceptor(){
    		//super表示显示调用父类有參数的构造器
    		//显示调用父类构造器之后,程序将不会隐式调用父类无參数的构造器
    		super(Phase.PRE_INVOKE);//该拦截器将会调用之前拦截SOAP消息
    	}
    	//实现自己的拦截器时。须要实现handleMessage方法。
    	//handleMessage方法中的形參就是被拦截到的Soap消息
    	//一旦程序获取了SOAP消息,剩下的事情就能够解析SOAP消息或改动SOAP消息
    	@Override
    	public void handleMessage(SoapMessage msg) throws Fault {
    		
    		System.out.println("-------"+msg);
    		//从这里能够看出,我们已经拦截到了SOAP消息
    		
    		//得到SOAP消息全部Header
    		List<Header> headers=msg.getHeaders();
    		
    		//假设没有Header
    		if(headers==null||headers.size()<1){
    			throw new Fault(new IllegalArgumentException("根本没有Header,不能调用"));						
    		}
    		
    		//假如要求第一个Header携带了username,password信息
    		Header firstHeader=headers.get(0);
    		Element ele=(Element)firstHeader.getObject();
    		
    		NodeList userIds=ele.getElementsByTagName("userId");
    		NodeList userPasses=ele.getElementsByTagName("userPass");
    		
    		if(userIds.getLength()!=1){
    			throw new Fault(new IllegalArgumentException("username的格式不对。"));
    		}
    		if(userPasses.getLength()!=1){
    			throw new Fault(new IllegalArgumentException("password的格式不对!"));
    		}
    		
    		//得到第一个userId元素里的文本内容。以该内容作为username字
    		String userId=userIds.item(0).getTextContent();
    		String userPass=userPasses.item(0).getTextContent();
    		//实际项目中。应该去查询数据库,该usernamepassword是否被授权调用web service
    		if(!userId.equals("hejingyuan") || !userPass.equals("hjy")){
    			throw new Fault(new IllegalArgumentException("usernamepassword不对!"));
    		}
    	}
    
    }
    

    客户端代码:


    package hjy;
    
    import java.util.List;
    
    import org.apache.cxf.endpoint.Client;
    import org.apache.cxf.frontend.ClientProxy;
    
    import com.tgb.auth.AddHeaderInterceptor;
    import com.tgb.service.Cat;
    import com.tgb.service.HelloWorld;
    import com.tgb.service.User;
    import com.tgb.service.impl.HelloWorldImpl;
    
    public class ClientMain {
    
    	public static void main(String[] args){
    		HelloWorldImpl factory=new HelloWorldImpl();
    		//此处返回的仅仅是远程Web Service的代理
    		HelloWorld hw=factory.getHelloWorldImplPort();
    		
    		Client client=ClientProxy.getClient(hw);
    		//參数为输入的username。password
    		client.getOutInterceptors().add(new AddHeaderInterceptor("hejingyuan","hjy"));
    		
    		System.out.println(hw.sayHi("hejingyuan"));
    		
    		System.out.println("--------------------------");
    		
    		User user=new User();
    		user.setId(20);
    		user.setName("孙悟空");
    		user.setPass("111");
    		user.setAddress("花果山");
    		
    		List<Cat> cats=hw.getCatsByUser(user);
    		for(Cat cat:cats){
    			System.out.println(cat.getName());
    		}
    		
    		System.out.println("--------------------------");
    		
    		System.out.println(hw.getAllCats().getEntry().get(0).getKey());
    		System.out.println(hw.getAllCats().getEntry().get(0).getValue().getName());
    		
    
    	}
    }

    AddHeaderInterceptor:


    package com.tgb.auth;
    
    import java.util.List;
    
    import javax.xml.namespace.QName;
    
    import org.apache.cxf.binding.soap.SoapMessage;
    import org.apache.cxf.headers.Header;
    import org.apache.cxf.helpers.DOMUtils;
    import org.apache.cxf.interceptor.Fault;
    import org.apache.cxf.phase.AbstractPhaseInterceptor;
    import org.apache.cxf.phase.Phase;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    
    
    public class AddHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
    
    	private String userId;
    	private String userPass;
    	
    	public AddHeaderInterceptor(String userId,String userPass){
    		super(Phase.PREPARE_SEND);//在准备发送SOAP消息时启用该拦截器
    		this.userId=userId;
    		this.userPass=userPass;
    	}
    	@Override
    	public void handleMessage(SoapMessage msg) throws Fault {
    		List<Header> headers=msg.getHeaders();
    		//创建Document对象
    		Document doc=DOMUtils.createDocument();
    		Element ele=doc.createElement("authHeader");
    		
    		//此处创建的元素应该依照server那边的要求
    		Element idEle=doc.createElement("userId");
    		idEle.setTextContent(userId);
    		Element passEle=doc.createElement("userPass");
    		passEle.setTextContent(userPass);
    		
    		ele.appendChild(idEle);
    		ele.appendChild(passEle);
    		
    		/**
    		 * 上面代码生成了一个例如以下XML文档片段
    		 * <authHeader>
    		 * 		<userId>hejingyuan</userId>
    		 * 		<userPass>hjy</userPass>
    		 * </authHeader>
    		 */
    		//把ele元素包装成Header,并加入到SOAP消息的Header列表中
    		headers.add(new Header(new QName("hejingyuan"),ele));
    	}
    
    }


    启动服务端的ServerMain的main函数。将服务公布。然后启动客户端ClientMain的main函数去訪问服务端提供的服务。

    usernamepassword错误时:




    usernamepassword正确时:




    总结:

     

    权限控制的实现方式为使用拦截器。对于拦截到的Soap消息进行改动。

    SOAP消息:

    根元素是Envolope

    Header

    默认情况下。Header元素不是强制出现的

    Header元素由程序猿控制加入,主要用户携带一些额外的信息。比方username,password信息

    Body

    假设调用正确,Body元素的内容应该遵守WSDL所要求的格式

    假设调用错误。Body元素的内容就是Fault子元素



    源代码下载



  • 相关阅读:
    90.子类调用父类同名方法总结
    89.子类调用父类同名属性和方法
    88.子类调用父类同名属性和方法
    87.子类重写父类的同名属性和方法
    86.多继承
    85.单继承
    84.继承的概念
    day09
    83.魔法方法__del__()
    82.魔法方法__str__()
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7120860.html
Copyright © 2011-2022 走看看