CXF中WS-Security自编码实现[转]

最近在做一个项目,两个异构系统中间需要进行数据交互,老大要求要保证安全性,数据交互方式初定为web service方式,用cxf实现。虽然CXF的WS-Security提供了比较全面的功能,但由于资料可以参考的资料太少,按照官方文档的试了一下没有跑通,就干脆自己做了一个。

 

异构系统之间的数据交互涉及到两个方面:

(1)传输的数据需要加密。比如从系统A向系统B发送了银行的账号和密码,这些信息是绝对不能在网络传输的过程中被截取到的。

(2)传输的系统间要建立信任关系。如果web service服务器发布了一个接收数据接口,是不能允许第三方不明身份的客户端调用这个接口的。

 

上述的两个安全性问题在所涉及的系统中,第二个问题比较重要,第一个问题只要不要明文出现就可以了,用一般的对称加密算法就可以了。所以问题的关键在于如何建立客户端和服务器端数据交换的数字证书。

 

对于数据的加密,目前比较公认的最保险的算法是非对称加密算法。基于非对称加密算法的思想,创建数字证书的思路为:客户端在调用服务器接口传输数据之前,先调用服务器端的一个接口,获取一个公钥;客户端用服务器端传输的公钥对一个共享密码进行加密,制造一个数字证书;服务器用自己保存的私钥和共享密码对证书进行验证。这样做有三个方面可以保证绝对保证安全:(1)服务器端每次产生的公钥和私钥对都是不同的、随机的;(2)共享密码是固定的,只有服务器端和被授权的客户端才知道,攻击方是不知道的;(3)共享密码制作的安全证书每次数据传输都是不同的,是不可伪造和修改无效的。

 

确定了方案,接下来只需要引入Srping的AOP功能,在客户端调用接口前系统执行安全相关的动作。相关代码如下:

 

web service 服务器端代码:

 

(1)服务器端产生公钥的接口:

import javax.jws.WebService;
@WebService
public interface ISignatureEncrp {  
 
 public String getIdentityKey()throws Exception; 

}

(2)服务器端实现公钥的类

import javax.jws.WebService;

@WebService(endpointInterface = "com.wanmei.wmqc.exclusr.IPasswordEncrp")
public class PasswordEncrpImpl implements ISignatureEncrp{   
  
 
 public String getIdentityKey()throws Exception{  
  
  Object[] temp = RSAManager.generaterKey();
  
  if(temp != null && temp.length>1){   
     ExcluServerConstants.KEY_PAIR_MAP.put(ExcluServerConstants.IDENTITY_KEY_PAIR, temp);
     return new String((byte[])temp[1]);
  }else{
      return null;
  }
 }
 
}

(3)RSA算法具体实现类

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Random;

public class RSAManager {
 
 
 public static Object[] generaterKey() throws Exception{
  java.security.KeyPairGenerator keygen = java.security.KeyPairGenerator.getInstance("RSA");
  SecureRandom secrand = new SecureRandom();
  String seedsur = "abc"; // random seeds.
  keygen.initialize(1024, secrand);
  KeyPair keys = keygen.genKeyPair(); 
  PublicKey pubkey = keys.getPublic();
  PrivateKey prikey = keys.getPrivate();  
  byte[] pubKey = Base64.encodeToByte(pubkey.getEncoded());
  byte[] priKey = Base64.encodeToByte(prikey.getEncoded());  
  Object[] result = new Object[2];
  result[0] = pubKey;
  result[1] = priKey;  
  return result;
 }
 
 
 public static byte[] sign(byte[] priKeyText, String plainText)throws Exception {
  PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
    Base64.decode(priKeyText));
  KeyFactory keyf = KeyFactory.getInstance("RSA");
  PrivateKey prikey = keyf.generatePrivate(priPKCS8);

  java.security.Signature signet = java.security.Signature.getInstance("MD5withRSA");
  signet.initSign(prikey);
  signet.update(plainText.getBytes());
  byte[] signed = Base64.encodeToByte(signet.sign());
  return signed;
 }
 
 
 public static boolean verify(byte[] pubKeyText, String plainText, byte[] signText) throws Exception{
  
  java.security.spec.X509EncodedKeySpec bobPubKeySpec =
     new java.security.spec.X509EncodedKeySpec(Base64.decode(pubKeyText));
  
  java.security.KeyFactory keyFactory = java.security.KeyFactory.getInstance("RSA");
  
  java.security.PublicKey pubKey = keyFactory.generatePublic(bobPubKeySpec);
  
  byte[] signed = Base64.decode(signText);
  java.security.Signature signatureChecker = java.security.Signature.getInstance("MD5withRSA");
  
  signatureChecker.initVerify(pubKey);
  signatureChecker.update(plainText.getBytes());  
  
  if (signatureChecker.verify(signed))
   return true;
  else
   return false;
 }

}

 

(4)beans.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:jaxws="http://cxf.apache.org/jaxws
    xsi:schemaLocation="  
        http://www.springframework.org/schema/beans   
        http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
        http://cxf.apache.org/jaxws   
        http://cxf.apache.org/schemas/jaxws.xsd">  
    <import resource="classpath:META-INF/cxf/cxf.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />  
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />  
   
    <bean id="serverPasswordCallback" 
        class="com.**.**.exclusr.ServerPasswordCallback" /> 
 
    <jaxws:endpoint id="exclusiveUser" 
        implementor="com.**.**.exclusr.ExclusiveUserImpl" address="/ExclUsr"> 
        
        <jaxws:inInterceptors>  
            <bean   class="org.apache.cxf.interceptor.LoggingInInterceptor" />           
        </jaxws:inInterceptors>
    </jaxws:endpoint>  
   
    <jaxws:endpoint id="signatureEncrp" 
        implementor="com.**.**.exclusr.SignatureEncrpImpl" address="/PwEncrp">
       
        <jaxws:inInterceptors>  
            <bean   class="org.apache.cxf.interceptor.LoggingInInterceptor" />           
        </jaxws:inInterceptors>
       
    </jaxws:endpoint>
 
</beans> 

 

web service客户端代码实现:

 

(1)公钥调用接口

import javax.jws.WebService;
@WebService
public interface ISignatureEncrp {  
 
 public String getIdentityKey()throws Exception; 

}

(2)自动执行安全处理的切面类

import java.util.Iterator;
import java.util.List;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Service;

@Service
@Aspect
public class EncrptionAspect {
 
 @Before("execution (* com.**.**.IExclusiveUser.sendSingleUser*(..)) && args(user,commPwd)")
 public void doSingleUserFilter(UserInfo user,CommPwdInfo commPwd)throws Exception{
    
  //初始化通讯密码:ExclusiveConstants.COMMUNICATION_PASSWORD
  RSAManager.initEncrpClient();
  commPwd.setCommunicationPwd(ExclusiveConstants.COMMUNICATION_PASSWORD); 

  
 }
 
}

 

(3)RSA实现类

 

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.List;

public class RSAManager { 
 
 public static byte[] sign(byte[] priKeyText, String plainText)throws Exception {
  PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec
        (Base64.decode(ExclusiveConstants.IDENTITY_PRIVATE_KEY.getBytes()));
  KeyFactory keyf = KeyFactory.getInstance("RSA");
  PrivateKey prikey = keyf.generatePrivate(priPKCS8);   

  java.security.Signature signet = java.security.Signature.getInstance("MD5withRSA");
  signet.initSign(prikey);
  signet.update(plainText.getBytes());
  byte[] signed = Base64.encodeToByte(signet.sign());
  return signed;
 }
 
 public static void initEncrpClient()throws Exception{
  IPasswordEncrp iencrp = (IPasswordEncrp)ExclusiveConstants.APPLICATION_CONTEXT
          .getBean(ExclusiveConstants.PASSWORD_ENCRP_INTERFACE);
  
  try {
   String priKey = iencrp.getIdentityKey();
   ExclusiveConstants.IDENTITY_PRIVATE_KEY = priKey;
    
   String password = new String(RSAManager.sign(priKey.getBytes(), ExclusiveConstants.IDENTITY_PASSWORD));
   ExclusiveConstants.COMMUNICATION_PASSWORD = password;
   
   } catch (Exception e1) {
    e1.printStackTrace();
   }
 }
 
}

 

(4)aop配置

<?xml version="1.0" encoding="UTF-8"?>
<!--
 Application context definition for PetClinic on Hibernate.
-->
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
   http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd
   http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
  
    <context:component-scan base-package="com.**.**.exclusr"/>

    <context:annotation-config/>
    <aop:aspectj-autoproxy/>

</beans>

(5)client-beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
             http://cxf.apache.org/jaxws
             http://cxf.apache.org/schemas/jaxws.xsd" >
                         
    <jaxws:client id="pwEncrp"
                serviceClass="com.**.**.exclusr.IPasswordEncrp"
                address="http://127.0.0.1:8080/ws/PwEncrp" >  
               
          <!--If the LoggingOutInterceptor is useless for you, you can delete it.  -->
          <jaxws:outInterceptors>
            <bean  class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
          </jaxws:outInterceptors>
          <!-- End LoggingOutInterceptor --> 
                   
    </jaxws:client>
   
    <jaxws:client id="exclUsrClient"
                  serviceClass="com.**.**.exclusr.IExclusiveUser"
                  address="http://127.0.0.1:8080/ws/ExclUsr" >
                 
        <!--If the LoggingOutInterceptor is useless for you, you can delete it.  -->
        <jaxws:outInterceptors>  
            <bean  class="org.apache.cxf.interceptor.LoggingOutInterceptor" />            
        </jaxws:outInterceptors>
        <!-- End LoggingOutInterceptor -->          
       
   </jaxws:client>    
     
   <bean id="clientPasswordCallback"  class="com.**.**.exclusr.ClientPasswordCallback" />  
  
</beans>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值