服务端基础设施开发----常用加解密插件+配置中心

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cdnight/article/details/86684903

前言

加解密插件是很常用的功能来的,加上去以后起码网站的安全性会高那么一点点。下面尝试用配置好的框架来写这个插件。插件包含aes,des,md5以及base64,注意,目前只是雏形,以后有需要会优化的。
这次整合到MasterWebApp模块中。

添加对应的配置类以及工具类

在WebExt下面添加对应的类,如下图:
在这里插入图片描述

代码分别是:

package net.w2p.WebExt.config;

/***
 *
 * 注意,这是加密解密组件的配置文件
 * ***/
public class CryptoConf {
    /***
     * AES/ECB/PKCS5Padding,Java版3DES加密解密的密钥,密钥为16的倍数,例如:AKlMU89D3FchIkhK
     * ***/
    public String aes_key="";
    /***
     * DES/CBC/PKCS5Padding,des加解密需要用到的私钥,长度不能够小于8位,例如:abcdefgh
     * ***/
    public String des_key="";
    /***
     *
     * md5使用的key
     * ***/
    public String md5_key="";

    public String getAes_key() {
        return aes_key;
    }

    public void setAes_key(String aes_key) {
        this.aes_key = aes_key;
    }

    public String getDes_key() {
        return des_key;
    }

    public void setDes_key(String des_key) {
        this.des_key = des_key;
    }

    public String getMd5_key() {
        return md5_key;
    }

    public void setMd5_key(String md5_key) {
        this.md5_key = md5_key;
    }
}

package net.w2p.WebExt.Plugins;


import net.w2p.WebExt.config.CryptoConf;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;

/***
 * 加解密插件。
 * ***/
public class CryptoPlugin {
    private CryptoConf conf=null;

    private  Cipher cipher4Aes = null;   //私鈅加密对象Cipher
    private  SecretKey secretKey4Aes = null;//key对象


    //des
    private final String ALGORITHM_DES = "DES/CBC/PKCS5Padding";
    private AlgorithmParameterSpec paramSpec4Des=null;
    private Key secretKey4Des=null;
    private Cipher cipher4Des=null;

    //md5
    protected char md5hexDigits[] = { '0', '1', '2', '3', '4', '5', '6',  '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    protected static MessageDigest md5messagedigest = null;

    public CryptoPlugin(CryptoConf conf) throws Exception {
        this.conf=conf;

        //--aes初始化

//            secretKey = new SecretKeySpec(keyString.getBytes(), "DESede");//获得密钥
        secretKey4Aes = new SecretKeySpec(this.conf.aes_key.getBytes(), "AES");//获得密钥
        /*获得一个私鈅加密类Cipher,DESede是算法,ECB是加密模式,PKCS5Padding是填充方式*/
//            cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        /*获得一个私鈅加密类Cipher,DESede-》AES算法,ECB是加密模式,PKCS5Padding是填充方式*/
        cipher4Aes = Cipher.getInstance("AES/ECB/PKCS5Padding");

        //--des初始化。

        DESKeySpec dks = new DESKeySpec(this.conf.des_key.getBytes());
        SecretKeyFactory keyFactory4Des = SecretKeyFactory.getInstance("DES");
        //key的长度不能够小于8位字节
        secretKey4Des = keyFactory4Des.generateSecret(dks);
        cipher4Des = Cipher.getInstance(ALGORITHM_DES);
        paramSpec4Des = new IvParameterSpec(this.conf.des_key.getBytes());
        cipher4Des.init(Cipher.ENCRYPT_MODE, secretKey4Des, paramSpec4Des);

        //--md5初始化
        md5messagedigest = MessageDigest.getInstance("MD5");


    }


    /***base64 begin***/
    /**
     *
     * 创建日期2011-4-25上午10:12:38
     * 修改日期
     * 作者:dh
     *TODO 使用Base64加密算法加密字符串
     *return
     */
    public String encodeBase64(String plainText){
        byte[] b=plainText.getBytes();
        Base64 base64=new Base64();
        b=base64.encode(b);
        String s=new String(b);
        return s;
    }
    /**
     *
     * 创建日期2011-4-25上午10:12:38
     * 修改日期
     * 作者:dh
     *TODO 使用Base64加密算法加密字符串
     *return
     */
    public String encodeBase64(byte[] bytes){
        byte[] b=bytes;
        Base64 base64=new Base64();
        b=base64.encode(b);
        String s=new String(b);
        return s;
    }
    /**
     *
     * 创建日期2011-4-25上午10:15:11
     * 修改日期
     * 作者:dh
     *TODO 使用Base64加密
     *return
     */
    public String decodeBase64(String encodeStr){
        byte[] b=encodeStr.getBytes();
        Base64 base64=new Base64();
        b=base64.decode(b);
        String s=new String(b);
        return s;
    }
    /**
     *
     * 创建日期2011-4-25上午10:15:11
     * 修改日期
     * 作者:dh
     *TODO 使用Base64加密
     *return
     */
    public byte[] decodeBase64(byte[] bytes){
        byte[] b=bytes;
        Base64 base64=new Base64();
        b=base64.decode(b);

        return b;
    }
    /***base64 end***/


    /***Aes begin***/

    /**
     * Aes加密
     * @param message
     * @return
     */
    public String AesEncrypt(String message) throws Exception {
        String result = "";   //DES加密字符串
        String newResult = "";//去掉换行符后的加密字符串

        cipher4Aes.init(Cipher.ENCRYPT_MODE, secretKey4Aes);     //设置工作模式为加密模式,给出密钥
        byte[] resultBytes = cipher4Aes.doFinal(message.getBytes("UTF-8")); //正式执行加密操作
        BASE64Encoder enc = new BASE64Encoder();
        result = enc.encode(resultBytes);//进行BASE64编码
        newResult = filter(result);      //去掉加密串中的换行符
        return newResult;
    }

    /**
     * Aes解密
     * @param message
     * @return
     * @throws Exception
     */
    public String AesDecrypt(String message) throws Exception {
        String result = "";
        BASE64Decoder dec = new BASE64Decoder();
        byte[] messageBytes = dec.decodeBuffer(message);  //进行BASE64编码
        cipher4Aes.init(Cipher.DECRYPT_MODE, secretKey4Aes);      //设置工作模式为解密模式,给出密钥
        byte[] resultBytes = cipher4Aes.doFinal(messageBytes);//正式执行解密操作
        result = new String(resultBytes,"UTF-8");
        return result;
    }


    /**
     * aes 加密解密时候去掉加密字符串换行符
     * @param str
     * @return
     */
    public String filter(String str) {
        String output = "";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < str.length(); i++) {
            int asc = str.charAt(i);
            if (asc != 10 && asc != 13) {
                sb.append(str.subSequence(i, i+1));
            }
        }
        output = new String(sb);
        return output;
    }
    /***Aes end***/


    /****Des begin***/

    /**
     * DES算法,加密
     *
     * @param data 待加密字符串
     * @return 加密后的字节数组,一般结合Base64编码使用
     * @throws CryptException 异常
     */
    public String DesEncrypt(String data) throws Exception
    {
        return DesEncrypt(data.getBytes());
    }
    /**
     * DES算法,加密
     *
     * @param data 待加密字符串
     * @param key  加密私钥,长度不能够小于8位
     * @return 加密后的字节数组,一般结合Base64编码使用
     * @throws CryptException 异常
     */
    public   String DesEncrypt(byte[] data) throws Exception
    {
        try
        {
            cipher4Des.init(Cipher.ENCRYPT_MODE, secretKey4Des,paramSpec4Des);
            byte[] bytes = cipher4Des.doFinal(data);
//            return byte2hex(bytes);
            return new String(encodeBase64(bytes));
        } catch (Exception e)
        {
            throw new Exception(e);
        }
    }

    /**
     * DES算法,解密
     *
     * @param data 待解密字符串
     * @param key  解密私钥,长度不能够小于8位
     * @return 解密后的字节数组
     * @throws Exception 异常
     */
    public byte[] DesDecrypt(byte[] data) throws Exception
    {
        try
        {


            cipher4Des.init(Cipher.DECRYPT_MODE, secretKey4Des,paramSpec4Des);
            return cipher4Des.doFinal(data);
        } catch (Exception e)
        {
            throw new Exception(e);
        }
    }

    /**
     * des算法,解密
     * @param data
     * @return
     * @throws Exception
     */
    public  String DesDecrypt(String data)
    {
        byte[] datas;
        String value = null;
        try {
            datas = DesDecrypt(decodeBase64(data.getBytes()));
            value = new String(datas);
        } catch (Exception e) {
            value = "";
        }
        return value;
    }

    /****Des end***/

    /***md5 begin***/

    /**
     * MD5方法
     *
     * @param text 明文     *
     * @return 密文
     * @throws Exception
     */
    public String md5WithKey(String text) throws Exception {
        //加密后的字符串
        return md5((text+conf.md5_key).getBytes());
    }
    public String md5WithoutKey(String text) throws Exception {
        //加密后的字符串
        return md5(text.getBytes());
    }
    /**
     * 对byte类型的数组进行MD5加密
     *
     * @author 高焕杰
     */
    public String md5(byte[] bytes) throws Exception {
        md5messagedigest.update(bytes);
        return bufferToHex(md5messagedigest.digest());
    }
//
    private String bufferToHex(byte bytes[]) {
        return bufferToHex(bytes, 0, bytes.length);
    }

    private String bufferToHex(byte bytes[], int m, int n) {
        StringBuffer stringbuffer = new StringBuffer(2 * n);
        int k = m + n;
        for (int l = m; l < k; l++) {
            char c0 = md5hexDigits[(bytes[l] & 0xf0) >> 4];
            char c1 = md5hexDigits[bytes[l] & 0xf];
            stringbuffer.append(c0);
            stringbuffer.append(c1);
        }
        return stringbuffer.toString();
    }

    /**
     * MD5验证方法
     *
     * @param text 明文
     * @param md5 密文
     * @return true/false
     * @throws Exception
     */
    public boolean verifyMD5(String text, String md5) throws Exception {
        //根据传入的密钥进行验证
        String md5Text = md5WithKey(text);
        if(md5Text.equalsIgnoreCase(md5))
        {
            System.out.println("MD5验证通过");
            return true;
        }

        return false;
    }
    /***md5 end***/


}


初始化配置中心的数据

请执行

create or replace function "initCryptoConfig"(
in envName varchar
)
returns varchar
as $BODY$
  declare _defaultValues varchar;
  declare _envName varchar;
  declare _appname varchar;
  declare _prefix varchar;
  declare strArrays varchar[];

  declare arrItemLv1 varchar;
  declare tempArrSubItem varchar;
  declare valArrs varchar[];

  declare item_attr varchar;
  declare item_title varchar;
  declare item_val varchar;
  declare _appDesc varchar;
  begin

    if envName <> 'test' and envName<> 'ppe' and envName<> 'product' then

      raise notice '环境变量异常,只能为test、ppe以及product其中一个。';
      return '环境变量异常,只能为test、ppe以及product其中一个。';

    end if;

    _appname:='crypto';
    _appDesc:='加解密设置(系统通用)';
    _prefix:=concat(_appname,'.','');
  _defaultValues:=
    'aes_key->AES/ECB/PKCS5Padding,Java版3DES加密解密的密钥,密钥为16的倍数,例如:12345678abcdefgh->12345678abcdefgh$$' ||
    'des_key->DES/CBC/PKCS5Padding,des加解密需要用到的私钥,长度不能够小于8位,例如:abcdefgh->abcdefgh$$' ||
    'md5_key->md5_key,随意字符串,例如:13579->13579$$' ||
    ''
    ;

  strArrays:=string_to_array(_defaultValues,'$$');
  _envName:=envName;

--   fastdfs.connect_timeout_in_seconds = 5
--     fastdfs.network_timeout_in_seconds = 30
--     fastdfs.charset = UTF-8
--     fastdfs.http_anti_steal_token = false
--     fastdfs.http_secret_key = FastDFS1234567890
--     fastdfs.http_tracker_http_port = 80
--                                        #fastdfs.tracker_servers = tw-server:22122,10.0.11.202:22122,10.0.11.203:22122
--     fastdfs.tracker_servers = localhost:22122
--     fastdfs.visit_url = http://localhost/

--   env     varchar(100) not null,
--     key     varchar(200) not null,
--     appname varchar(100) not null,
--     title   varchar(100) not null,
--     value   varchar(2000) default NULL::character varying,

insert into xxl_conf_project (appname, title) values (_appname,_appDesc) on conflict ("appname") do nothing;
  <<loop4BigArray>>
    foreach arrItemLv1 in array  strArrays

      loop

        if char_length(arrItemLv1) < 1 then
          raise notice '空字符串无须处理';
          continue ;
        end if;
        valArrs:=string_to_array(arrItemLv1,'->');
        item_attr:=valArrs[1];
        item_title:=valArrs[2];
        item_val:=valArrs[3];

      raise notice '属性名称:%,描述:%,当前值:%',item_attr,item_title,item_val;
      raise notice '开始添加记录';
        insert into xxl_conf_node("env","key","appname","title","value")
        values (_envName,concat(_prefix,item_attr),_appname,item_title,item_val)
        on conflict ("env","key") do nothing ;

    end loop loop4BigArray;


    return envName||'环境下的'||_appName||'配置成功';
  end;

  $BODY$ language plpgsql volatile ;
-- 记住执行下面方法分别添加三个环境下的默认数据。
-- select "initCryptoConfig"('test');
-- select "initCryptoConfig"('ppe');
-- select "initCryptoConfig"('product');


用工具远程登录配置中心的数据库,直接执行即可:

select "initCryptoConfig"('test');
select "initCryptoConfig"('ppe');
select "initCryptoConfig"('product');

使用java代码整合到spring中进行设置

在MasterWebApp中整合。

在MasterWebApp的BeanConfiguration下面添加:

package net.w2p.local.plugins.BeanConfiguration;

import com.xxl.conf.core.XxlConfClient;
import net.w2p.WebExt.Plugins.CryptoPlugin;
import net.w2p.WebExt.config.CryptoConf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/***
 *
 * 系统加解密插件配置
 * ***/
@Configuration
public class CryptoConfiguration {
    @Bean(name="cryptoConf")
    public CryptoConf cryptoConf(){
        final String  VarPrefix ="crypto.";
        CryptoConf conf=new CryptoConf();
        conf.aes_key = XxlConfClient.get(VarPrefix+"aes_key");
        conf.des_key = XxlConfClient.get(VarPrefix+"des_key");
        conf.md5_key = XxlConfClient.get(VarPrefix+"md5_key");
        return conf;
    }

    @Bean(name="cryptoPlugin")
    @Autowired
    public CryptoPlugin cryptoPlugin(@Qualifier("cryptoConf") CryptoConf conf){
        try {
            CryptoPlugin plugin = new CryptoPlugin(conf);
            return plugin;
        }
        catch (Exception ed){
            ed.printStackTrace();
            return null;
        }
    }
}

进行测试

测试代码如下:

    @Test
    public void testCrypto() throws Exception {

        if(1==1){
            String flag="Aes--->";
            System.out.println(flag);
            String res="nihao,你好,hello";
            String enc=cryptoPlugin.AesEncrypt(res);
            String dec=cryptoPlugin.AesDecrypt(enc);

            System.out.println(flag+"原始数据:"+res);
            System.out.println(flag+"加密后:"+enc);
            System.out.println(flag+"解密后:"+dec);

            res="well,done!!!?><:L";
            enc=cryptoPlugin.AesEncrypt(res);
            dec=cryptoPlugin.AesDecrypt(enc);

            System.out.println(flag+"原始数据:"+res);
            System.out.println(flag+"加密后:"+enc);
            System.out.println(flag+"解密后:"+dec);

        }

        if(1==1){
            String flag="Des--->";
            System.out.println(flag);
            String res="nihao,你好,hello";
            String enc=cryptoPlugin.DesEncrypt(res);
            String dec=cryptoPlugin.DesDecrypt(enc);

            System.out.println(flag+"原始数据:"+res);
            System.out.println(flag+"加密后:"+enc);
            System.out.println(flag+"解密后:"+dec);

            res="well,done!!!?><:L";
            enc=cryptoPlugin.DesEncrypt(res);
            dec=cryptoPlugin.DesDecrypt(enc);

            System.out.println(flag+"原始数据:"+res);
            System.out.println(flag+"加密后:"+enc);
            System.out.println(flag+"解密后:"+dec);

        }

        if(1==1){
            String flag="MD5--->";
            System.out.println(flag);
            String res="nihao,你好,hello";
            String enc=cryptoPlugin.md5WithKey(res);


            System.out.println(flag+"原始数据:"+res);
            System.out.println(flag+"加密后:"+enc);


            res="well,done!!!?><:L";
            enc=cryptoPlugin.md5WithKey(res);


            System.out.println(flag+"原始数据:"+res);
            System.out.println(flag+"加密后:"+enc);


        }
    }

测试结果:

在这里插入图片描述

插件基本通过验收。后续的组件将用到这个插件的。所以,还是安上去好点。

猜你喜欢

转载自blog.csdn.net/cdnight/article/details/86684903