浏览 6562 次
锁定老帖子 主题:为Hessian加入加密签名的安全机制
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-03-09
我在项目的开发中为了解决Hessian的安全问题,在HTTP头中加入了签名信息。 首先要继承HessianProxyFactory在HTTP头中加入时间戳和签名 /** * @author Buffon * */ public class YeatsHessianProxyFactory extends HessianProxyFactory { private long connectTimeOut = 0; private String signature; private long timeStamp; /** * @return signature */ public String getSignature() { return signature; } /** * @param signature * 要设置的 signature */ public void setSignature(String signature) { this.signature = signature; } /** * @return connectTimeOut */ public long getConnectTimeOut() { return connectTimeOut; } /** * @param connectTimeOut * 要设置的 connectTimeOut */ public void setConnectTimeOut(long connectTimeOut) { this.connectTimeOut = connectTimeOut; } public URLConnection openConnection(URL url) throws IOException { URLConnection conn = super.openConnection(url); if (connectTimeOut > 0) { try { // only available for JDK 1.5 Method method = conn.getClass().getMethod("setConnectTimeout", new Class[] { int.class }); if (method != null) method.invoke(conn, new Object[] { new Integer( (int) connectTimeOut) }); } catch (Throwable e) { } } if (!StringUtil.isEmptyOrWhitespace(this.signature)) { conn.setRequestProperty("Yeats-Signature", this.signature); } if (this.timeStamp > 0) { conn.setRequestProperty("Yeats-Timestamp", Long .toString(this.timeStamp)); } return conn; } /** * @return timeStamp */ public long getTimeStamp() { return timeStamp; } /** * @param timeStamp * 要设置的 timeStamp */ public void setTimeStamp(long timeStamp) { this.timeStamp = timeStamp; } } 关键之处就在于openConnection方法覆盖了HessianProxyFactory的openConnection方案在原有的openConnection方法基础上加入了链接超时的设置,及时间戳和签名。 继承HessianProxyFactoryBean使proxyFactory设置为上面的子类实现 /** * @author Buffon * */ public class YeatsHessianProxyFactoryBean extends HessianProxyFactoryBean { private YeatsHessianProxyFactory proxyFactory = new YeatsHessianProxyFactory(); private long readTimeOut; private long connectTimeOut; private String crypt; private DSA dsaService; /** * @return crypt */ public String getCrypt() { return crypt; } /** * @param crypt * 要设置的 crypt */ public void setCrypt(String crypt) { this.crypt = crypt; } /** * @return connectTimeOut */ public long getConnectTimeOut() { return connectTimeOut; } /** * @param connectTimeOut * 要设置的 connectTimeOut */ public void setConnectTimeOut(long connectTimeOut) { this.connectTimeOut = connectTimeOut; } /** * @return readTimeOut */ public long getReadTimeOut() { return readTimeOut; } /** * @param readTimeOut * 要设置的 readTimeOut */ public void setReadTimeOut(long readTimeOut) { this.readTimeOut = readTimeOut; } public void afterPropertiesSet() { proxyFactory.setReadTimeout(readTimeOut); proxyFactory.setConnectTimeOut(connectTimeOut); long timeStamp = new Date().getTime(); proxyFactory.setTimeStamp(timeStamp); try { proxyFactory.setSignature(this.createSignature(timeStamp, this.crypt)); } catch (Exception e) { } setProxyFactory(proxyFactory); super.afterPropertiesSet(); } private String createSignature(long timeStamp, String crypt) throws Exception { if (timeStamp <= 0 || StringUtil.isEmptyOrWhitespace(crypt)) { throw new Exception("timestamp or crypt is invalied"); } StringBuilder sb = new StringBuilder(); sb.append("{"); sb.append(timeStamp); sb.append("},{"); sb.append(crypt); sb.append("}"); return dsaService.sign(sb.toString()); } /** * @return dsaService */ public DSA getDsaService() { return dsaService; } /** * @param dsaService 要设置的 dsaService */ public void setDsaService(DSA dsaService) { this.dsaService = dsaService; } } dsaService的实现请参考我的另一篇文章《java加入DSA签名》,createSignature方法中签名的明文组成形式是“{时间戳},{密码字符串}” 继承HessianServiceExporter对签名进行校验 /** * @author Buffon * */ public class YeatsHessianServiceExporter extends HessianServiceExporter { private static final Log log = LogFactory.getLog(YeatsHessianServiceExporter.class); private DSA dsaService; private String crypt; private long timeValve; public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String signature = request.getHeader("Yeats-Signature"); String timestamp = request.getHeader("Yeats-Timestamp"); if (StringUtil.isEmptyOrWhitespace(signature)) { log.error("Can't get signature"); throw new ServletException("Can't get signature"); } if (StringUtil.isEmptyOrWhitespace(timestamp)) { log.error("Cant't get timestamp"); throw new ServletException("Cant't get timestamp"); } long now = new Date().getTime(); long range = now - Long.parseLong(timestamp); if (range < 0) { range = -range; } if (range > timeValve) { log.error("Timestamp is timeout"); throw new ServletException("Timestamp is timeout"); } StringBuilder sb = new StringBuilder(); sb.append("{"); sb.append(timestamp); sb.append("},{"); sb.append(crypt); sb.append("}"); try { if (dsaService.verify(signature, sb.toString())) { super.handleRequest(request, response); } else { log.error("No permission"); throw new ServletException("No permission"); } } catch (Exception e) { log.error("Failed to process remote request!", e); throw new ServletException(e); } } /** * @return dsaService */ public DSA getDsaService() { return dsaService; } /** * @param dsaService * 要设置的 dsaService */ public void setDsaService(DSA dsaService) { this.dsaService = dsaService; } /** * @return crypt */ public String getCrypt() { return crypt; } /** * @param crypt * 要设置的 crypt */ public void setCrypt(String crypt) { this.crypt = crypt; } /** * @return timeValve */ public long getTimeValve() { return timeValve; } /** * @param timeValve * 要设置的 timeValve */ public void setTimeValve(long timeValve) { this.timeValve = timeValve; } } 覆盖handleRequest方法,在验证通过后再调用父类的handleRequest方法。timeValve为时间戳的校验范围,如果请求到达时间大于这个范围,此请求被认为是非法请求不会再做处理 客户端SPRING配置 <bean id="searchService" class="com.yeatssearch.remote.hessian.YeatsHessianProxyFactoryBean"> <property name="serviceUrl" value="http://localhost:8080/Test/remoting/TestService" /> <property name="serviceInterface" value="com.yeatssearch.test.TestService" /> <property name="readTimeOut" value="30000"/> <property name="connectTimeOut" value="5000"/> <property name="crypt" value="sdfsfdsfsdfsdfsdf"/> <property name="dsaService" ref="dsaService"></property> </bean> 服务器端SPRING配置 <bean name="/TestService" class="com.yeatssearch.remote.hessian.YeatsHessianServiceExporter"> <property name="service" ref="testService" /> <property name="serviceInterface" value="com.yeatssearch.test.TestService" /> <property name="timeValve" value="30000"/> <property name="crypt" value="sdfsfdsfsdfsdfsdf"/> <property name="dsaService" ref="dsaService"/> </bean> 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-03-11
问题是要实现通讯数据的加密而不是简单的调用认证啊
|
|
返回顶楼 | |
发表时间:2008-06-30
别扯了,hessian的加密和认证都有的
|
|
返回顶楼 | |
发表时间:2008-08-05
hessian内置的加密和认证如何使用呢?经过多方搜索无果。
|
|
返回顶楼 | |
发表时间:2008-08-05
认证好像是通过http basice的方式。加密没有使用过
|
|
返回顶楼 | |
发表时间:2008-08-05
建议楼主看看hessian源代码, 其实是有的: X509Signature extends HessianEnvelope X509Encryption extends HessianEnvelope |
|
返回顶楼 | |