hessian-添加安全机制

来源:互联网 发布:php面试题读取一个文件 编辑:程序博客网 时间:2024/06/03 16:07

Hessian和Burlap是caucho公司提供的开源协议,基于HTTP传输,服务端不用开防火墙端口。协议的规范公开,可以用于任意语言。
相比于常用的RPC协议WebService来说,hessian更加简单高效,速度更快,只需要简单的配置即可,无需生成任何类。相对于RMI
来说,hessian支持多种语言和平台,速度也不逊于前者。相对于ICE,hessian是基于http协议,可以穿透防火墙,无需配置相关
设置。因为它是一个Servlet,底层性的工作,比如 输入输出流、并发、日志等事情都可以交给Tomcat、Resin,也便于横向扩容。

不过在使用中发现hessian框架本身也有自己的劣势,比如缺乏安全机制,缺乏超时设置等等。在pop订单中心搭建的过程中,
也参考了网上一些解决方案,在hessian和spring原有的类上面做了扩展,加入了token验证,客户端超时时间配置和最大线程数
限制。配置方式如下:

123456789101112
<bean id="offlineOrderServiceClient"          class="com.tmaic.util.MyHessianProxyFactoryBean">        <property name="serviceUrl"                  value="http://127.0.0.1/hessian/helloHessian"/>        <property name="serviceInterface"                  value="com.tmaic.service.ShareWordService"/>        <property name="overloadEnabled" value="true"/>        <property name="connectTimeOut" value="30000"/>        <property name="readTimeOut" value="30000"/>        <property name="poolMaxSize" value="30"/>        <property name="token" value="123456"/>    </bean>

MyHessianProxyFactoryBean 类是继承自HessianProxyFactoryBean,通过spring注入可以方便的
在接入hessian接口时候根据自身接口的需求动态配置参数,connectTimeOut和readTimeOut 限制了最大
超时时间,poolMaxSize 限制了该客户端最大的线程数,token 则是对客户端的安全校验密钥。

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
public class MyHessianProxyFactoryBean extends HessianProxyFactoryBean{    private int readTimeOut = 500;    private int connectTimeOut = 30000;    private int poolMaxSize = 20;    private ReentrantLock lock = new ReentrantLock();    private Condition condition = lock.newCondition();    private AtomicInteger invokeCount = new AtomicInteger(0);    private String token;    public int getReadTimeOut() {        return readTimeOut;    }    public void setReadTimeOut(int readTimeOut) {        this.readTimeOut = readTimeOut;    }    public int getConnectTimeOut() {        return connectTimeOut;    }    public void setConnectTimeOut(int connectTimeOut) {        this.connectTimeOut = connectTimeOut;    }    public int getPoolMaxSize() {        return poolMaxSize;    }    public void setPoolMaxSize(int poolMaxSize) {        this.poolMaxSize = poolMaxSize;    }    public void setToken(String token) {        this.token = token;    }    @Override    public void prepare() throws RemoteLookupFailureException {        MyHessianProxyFactory proxyFactory = new MyHessianProxyFactory();        if(this.readTimeOut >0){            proxyFactory.setReadTimeOut(this.readTimeOut);        }        if(this.connectTimeOut >0){            proxyFactory.setConnectTimeOut(this.connectTimeOut);        }        if(StringUtils.isNotBlank(token)){            proxyFactory.setToken(token);        }        this.setProxyFactory(proxyFactory);        super.prepare();    }    @Override    public Object invoke(MethodInvocation invocation) throws Throwable {        this.lock.lock();        try{            if(invokeCount.get() > this.poolMaxSize){                System.out.println("invokeCount:"+invokeCount.get());                condition.await(this.readTimeOut, TimeUnit.MILLISECONDS);            }            if (invokeCount.get() > this.poolMaxSize) {                 throw new IOException("wait hessian pool timeout: poolSize:" +                         this.poolMaxSize + ", timeout:" + this.readTimeOut +", no="+invokeCount.get());            }            this.invokeCount.incrementAndGet();        }finally {            this.lock.unlock();        }        Object o = null;        try{            o=super.invoke(invocation);        }finally {            this.lock.lock();            try{                this.invokeCount.decrementAndGet();                condition.signal();            }finally {                this.lock.unlock();            }        }        return o;    }}

MyHessianProxyFactory
1234567891011121314151617181920212223242526272829303132333435363738394041424344
public class MyHessianProxyFactory extends HessianProxyFactory{    private int connectTimeOut = 30000;    private int readTimeOut = 30000;    private String token;    public int getConnectTimeOut() {        return connectTimeOut;    }    public void setConnectTimeOut(int connectTimeOut) {        this.connectTimeOut = connectTimeOut;    }    public int getReadTimeOut() {        return readTimeOut;    }    public void setReadTimeOut(int readTimeOut) {        this.readTimeOut = readTimeOut;    }    public String getToken() {        return token;    }    public void setToken(String token) {        this.token = token;    }    protected URLConnection openConnection(URL url) throws IOException {        URLConnection conn = super.openConnection(url);        if (this.connectTimeOut > 0) {            conn.setConnectTimeout(this.connectTimeOut);        }        if (this.readTimeOut > 0) {            conn.setReadTimeout(this.readTimeOut);        }        if(token!=null && !"".equals(token)){            conn.setRequestProperty("AUTH",token);        }        return conn;    }}

MyHessianServiceExporter

1234567891011121314151617181920212223242526272829
public class MyHessianServiceExporter extends HessianServiceExporter{    private String token;    private final static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(MyHessianServiceExporter.class);    @Override    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        String auth = request.getHeader("AUTH");        if(!checkTokenHeader(auth)){            logger.error("token is error!");            return;        }        super.handleRequest(request, response);    }    private boolean checkTokenHeader(String clientToken){        if (StringUtils.isBlank(clientToken)) {            return false;        }        if (StringUtils.isBlank(token)) {            return false;        }        return token.equals(clientToken);    }    //get set    public void setToken(String token) {        this.token = token;    }}
0 0