Hessian接口调用时的DSA 加密(转)

转载只是为了学习,我还得试一下行不行。呵呵。
来源:[url]http://dingjob.iteye.com/blog/689073[/url]

我们经常会使用hessian接口,但是hessian接口默认的情况下是不会进行加密的,原来在项目中使用了MD5的加密,这次希望通过DSA 加密解决 C- S的安全通讯,一方面确定客户端是有权限调用的(给出了publicKey),另一方面保证传输的数据安全

基本思路就是采用 新的HessianProxyFactory和 HessianServiceExporter 代替原来的发送和接收端,发送请求时进行私钥加密,接收时进行公钥的解密。

基本逻辑实现如下:


/**
* 实现带加密功能的hessian client
*
* <pre>
* 结合spring hessian使用,使用DSAHessianProxyFactory替换默认的HessianProxyFactory
* <bean id="heessianClient" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
* <property name="proxyFactory">
* <bean class="com.alibaba.pivot.common.hessian.DSAHessianProxyFactory">
* <property name="secureKey" value="xxxxx"/>
* </bean>
* </property>
* </bean>
* </pre>
*
* @author job 2010-01-28 上午10:20:01
*/
public class DSAHessianProxyFactory extends HessianProxyFactory {

private static final Logger log = LoggerFactory.getLogger(DSAHessianProxyFactory.class);

private DSAService dsaService;

private String keyPairName;

/**
* 固定的加密字符串
*/
private String secureKey;

protected URLConnection openConnection(URL url) throws IOException {
String signature = null;
String baseUrl = url.toString();
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append(baseUrl);

// 生成时间戳
long timestamp = System.currentTimeMillis();
// 生成方法签名
try {
signature = dsaService.sign(secureKey + "|" + Long.toString(timestamp), keyPairName);
} catch (NoSuchKeyPairException ne) {
log.error("error in DSAHessianProxyFactory.openConnection,no such key" + keyPairName, ne);
} catch (DSAException de) {
log.error("error in DSAHessianProxyFactory.openConnection,DSA sign error" + keyPairName, de);
}
if (!"?".equals(queryBuilder.charAt(queryBuilder.length() - 1))) {
queryBuilder.append("?");
}

queryBuilder.append("sign=");
if (signature != null) {
queryBuilder.append(StringEscapeUtil.escapeURL(signature));
}
queryBuilder.append("&time=");
queryBuilder.append(timestamp);
URL secureUrl = new URL(queryBuilder.toString());

URLConnection conn = secureUrl.openConnection();

conn.setDoOutput(true);

if (getReadTimeout() > 0) {
try {
conn.setReadTimeout((int) getReadTimeout());
} catch (Throwable e) {
}
}
// 设置自定义的content-type
conn.setRequestProperty("Content-Type", "application/octet-stream");

return conn;
}


输出时的加密:

 
/**
* 处理加密的hessian server, 代码来自pivot-p4p
*
* <pre>
* 1. timeout 设置超时时间,单位秒. (客户端会在每次请求中添加时间戳,如果设置了该值,就会进行对客户端请求时间是否超时进行验证)
* 2. secureKey 服务端密钥串 (如果设置了该值,就会进行对客户端请求加密串进行验证)
* 3. allowedClients 客户端IP验证 (如果设置了该值,就会进行对客户端请求IP进行验证)
* </pre>
*
* @author job 2010-01-28 上午09:53:02
*/
public class DSAHessianServiceExporter extends HessianServiceExporter {

private static Logger log = LoggerFactory.getLogger(DSAHessianServiceExporter.class);

/** 请求过期时间 **/
private long timeout;
/** 令牌原文 **/
private String secureKey;
/** 允许访问的客户端 **/
private String allowedClients;
/** dsa 加密服务 **/
private DSAService dsaService;
/** 密钥名称 **/
private String keyPairName;

public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
// 1.如果设置了允许的IP地址,需要进行客户端IP地址验证
if (StringUtil.isNotBlank(allowedClients)) {
String clientIP = getClientIPAddress(request);
if (!isAllowedClient(clientIP)) {
log.error("hessian authentication error:" + clientIP + " not in allowedList " + allowedClients);
return;
}
}

// 2.如果设置了令牌或者过期时间,需要判断时间格式是否合法
String strTimestamp = request.getParameter("time");
long timestamp = 0;
if (timeout > 0 || StringUtil.isNotBlank(secureKey)) {
if (strTimestamp == null) {
log.error("hessian authentication error:timestamp not exist!");
return;
}
try {
timestamp = Long.parseLong(strTimestamp);
} catch (NumberFormatException e) {
log.error("hessian authentication error:timestamp is not number!");
return;
}
}

// 3.如果设置了过期时间,需要判断请求是否过期
if (timeout > 0) {
// 判断请求是否过期
if (isRequestExpired(timestamp)) {
log.error("hessian authentication error:request is expired!");
return;
}
}

// 4. 如果设置了令牌,需要进行签名校验
if (StringUtil.isNotBlank(secureKey)) {
// 4.1 得到签名
String signature = request.getParameter("sign");
if (signature == null) {
log.error("hessian authentication error:signatures not exist!");
return;
}
try {
// 4.2 验证签名是否一致
boolean isRight = dsaService.check(secureKey + "|" + timestamp, signature, keyPairName);
if (!isRight) {
log.error("hessian authentication error:signatures not match!");
return;
}
} catch (NoSuchKeyPairException ne) {
log.error("error in DSAHessianServiceExporter.handleRequest,no such key" + keyPairName, ne);
} catch (DSAException de) {
log.error("error in DSAHessianServiceExporter.handleRequest,DSA sign error", de);
}

}
// 5. 设置hessian context-type
response.setContentType("application/octet-stream");
super.handleRequest(request, response);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值