PRC 技术实现:Hessian 基于DSA算法实现对时间戳签名验证

来源:互联网 发布:知乎文字复制 编辑:程序博客网 时间:2024/06/15 09:47

        当今RPC的相关技术实现比较多,比如:Spring HttpInvoker,Hessian,Apache Thrift,Google Protobuf等。。。以上技术实现对比网上有很多,这里主要介绍一下Hessian(http://hessian.caucho.com/)的安全验证的一种实现方案,hessian本身支持基于app server的用户名+密码验证,本文更进一步,基于DSA算法,实现对时间戳签名验证:

1.密钥对生成类,生成公钥和私钥

public class keyGenerator {private static KeyPairGenerator kpg = null;private static KeyPair kp = null;private static PublicKey public_key = null;private static PrivateKey private_key = null;private static FileOutputStream public_file_out = null;private static ObjectOutputStream public_object_out = null;private static FileOutputStream private_file_out = null;private static ObjectOutputStream private_object_out = null;public static void main(String[] args) {try {kpg = KeyPairGenerator.getInstance("DSA"); // 创建‘密匙对’生成器kpg.initialize(1024); // 指定密匙长度(取值范围:512~2048)kp = kpg.genKeyPair(); // 生成‘密匙对’,其中包含着一个公匙和一个私匙的信息public_key = kp.getPublic(); // 获得公匙private_key = kp.getPrivate(); // 获得私匙// 保存公匙public_file_out = new FileOutputStream("d:" + "/public_key.dat");public_object_out = new ObjectOutputStream(public_file_out);public_object_out.writeObject(public_key);// 保存私匙private_file_out = new FileOutputStream("d:" + "/private_key.dat");private_object_out = new ObjectOutputStream(private_file_out);private_object_out.writeObject(private_key);} catch (Exception e) {e.printStackTrace();}}}

2.签名实现类,负责加签和验签

public class SimpleSignatureService implements SignatureService {protected Logger log = LoggerFactory.getLogger(getClass());private String algonrithm = "DSA";private PublicKey publicKey;private PrivateKey privateKey;/** * 签名 */@Overridepublic String sign(String content) throws Exception {try {Signature signature = Signature.getInstance(algonrithm);signature.initSign(privateKey);signature.update(content.getBytes());byte[] result = signature.sign();return EncodeUtils.hexEncode(result);} catch (Exception e) {log.error(e.getMessage(), e);throw e;}}/** * 验签 */@Overridepublic boolean verify(String signature, String content) throws Exception {try {Signature verifyalg = Signature.getInstance(algonrithm);verifyalg.initVerify(publicKey);verifyalg.update(content.getBytes());return verifyalg.verify(EncodeUtils.hexDecode(signature));} catch (Exception e) {log.error(e.getMessage(), e);throw e;}}public void setPrivateKey(Resource privateKeyResource) throws Exception {try {ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(privateKeyResource.getFile()));privateKey = (PrivateKey) keyIn.readObject();keyIn.close();} catch (Exception e) {log.error(e.getMessage(), e);throw e;}}public void setPublicKey(Resource publicKeyResource) throws Exception {try {ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(publicKeyResource.getFile()));publicKey = (PublicKey) keyIn.readObject();keyIn.close();} catch (Exception e) {log.error(e.getMessage(), e);throw e;}}}

3.Hessian服务导出实现类(服务端使用)

public class SecurityHessianServiceExporter extends HessianServiceExporter {protected Logger log = LoggerFactory.getLogger(getClass());private SignatureService signatureService;private long expireTime;//timestamp有效期(毫秒)private String token;public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {Assert.notNull(token, "Token 不允许为空!");String signature = request.getHeader("_TShark_Signature");String timestamp = request.getHeader("_TShark_Timestamp");if (StringUtil.isEmpty(signature)) {log.error("Signature is empty!");throw new ServletException("Signature is empty!");}if (StringUtil.isEmpty(timestamp)) {log.error("Timestamp is empty!");throw new ServletException("Timestamp is empty!");}if (expireTime > 0) {long now = new Date().getTime();long range = now - Long.parseLong(timestamp);if (range < 0) {range = -range;}if (range > expireTime) {log.error("Timestamp is timeout");throw new ServletException("Timestamp is timeout");}}try {if (signatureService.verify(signature, timestamp + "#" + token)) {super.handleRequest(request, response);} else {log.error("Signature is invalid!");throw new ServletException("Signature is invalid!");}} catch (Exception e) {log.error("Failed to process remote request!", e);throw new ServletException(e);}}public SignatureService getSignatureService() {return signatureService;}public void setSignatureService(SignatureService signatureService) {this.signatureService = signatureService;}public long getExpireTime() {return expireTime;}public void setExpireTime(long expireTime) {this.expireTime = expireTime;}public String getToken() {return token;}public void setToken(String token) {this.token = token;}}
4.Hessian代理工厂类(客户端使用)

public class SecurityHessianProxyFactory extends HessianProxyFactory {protected Logger log = LoggerFactory.getLogger(getClass());private SignatureService signatureService;private int connectTimeout = 0;private String token;public URLConnection openConnection(URL url) throws IOException {URLConnection conn = super.openConnection(url);if (connectTimeout > 0) {conn.setConnectTimeout(connectTimeout);}long timestamp = new Date().getTime();//对timestamp进行签名conn.setRequestProperty("_TShark_Signature", createSignatureByTimestamp(timestamp));conn.setRequestProperty("_TShark_Timestamp", Long.toString(timestamp));return conn;}private String createSignatureByTimestamp(long timestamp) {try {return signatureService.sign(timestamp + "#" + token);} catch (Exception e) {log.error(e.getMessage(), e);throw new TSharkException(e);}}public SignatureService getSignatureService() {return signatureService;}public void setSignatureService(SignatureService signatureService) {this.signatureService = signatureService;}public int getConnectTimeout() {return connectTimeout;}public void setConnectTimeout(int connectTimeout) {this.connectTimeout = connectTimeout;}public String getToken() {return token;}public void setToken(String token) {this.token = token;}}
5.服务端配置文件applicationContext-remote.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"default-lazy-init="true"><bean id="xxxService" class="org.tshark.core.remote.http.SecurityHessianProxyFactoryBean"><property name="serviceUrl"value="http://xxx.xxx.xxx.xxx/XxxxServiceImpl" /><property name="serviceInterface" value="xxx.XxxxService" /><property name="proxyFactory" ref="hessianProxyFactory" /></bean><bean id="hessianProxyFactory" class="org.tshark.core.remote.http.SecurityHessianProxyFactory"><property name="connectTimeout" value="10000" /><property name="token" value="tshark-2012" /><property name="signatureService" ref="simpleSignatureService" /></bean><bean id="simpleSignatureService" class="org.tshark.core.security.impl.SimpleSignatureService"><property name="publicKey" value="classpath:public_key.dat" /><property name="privateKey" value="classpath:private_key.dat" /></bean></beans>

在web.xml中增加:

   <!--Hessian--><servlet><servlet-name>remote</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath*:applicationContext-remote.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet>    <servlet-mapping><servlet-name>remote</servlet-name><url-pattern>/remote/*</url-pattern></servlet-mapping>



6.客户端配置文件applicationContext-client.xml

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"default-lazy-init="true"><bean name="/XxxxService"class="org.tshark.core.remote.http.SecurityHessianServiceExporter"><property name="service" ref="xxxService" /><property name="serviceInterface" value="xxx.XxxxService" /><property name="signatureService" ref="simpleSignatureService" /><property name="token" value="tshark-security-2012" /><!--需要与服务端配置一致--></bean><bean id="simpleSignatureService" class="org.tshark.core.security.impl.SimpleSignatureService"><property name="publicKey" value="classpath:public_key.dat" /><property name="privateKey" value="classpath:private_key.dat" /></bean></beans>
7.客户端注入:xxxService类,调用其中方法即可






原创粉丝点击