RedisTemplate 对存入redis 中的json 字符串加密和解密

使用RedisTemplate 对redis操作时,存入的数据为明文时数据容易被盗,我了解决这个问题,我们可以对数据进行加密后再存入redis 中。具体操作如下:


1.启用缓存:
package com.tms.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tms.bean.system.client.Jackson2JsonRedisSerializerAes;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.lang.reflect.Method;


/**
* Redis 缓存配置
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{

//    @Bean
//    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//        RedisTemplate<String, String> redisTemplate = new RedisTemplate();
//        redisTemplate.setConnectionFactory(redisConnectionFactory);
//        return redisTemplate;
//    }


    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method
                    method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }


    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {

        StringRedisTemplate template = new StringRedisTemplate(factory);
//明文显示
  // Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new //Jackson2JsonRedisSerializer(Object.class);
//密文显示
        Jackson2JsonRedisSerializerAes jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializerAes(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        cacheManager.setDefaultExpiration(60*60*24*60);//设置过期时间 (秒)
        return cacheManager;
    }

}



2.编写加解密类:

package com.tms.bean.system.util;


import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Created by gjp on 2017/10/11.
*/
public class AESUtil {

    private static final String KEY_ALGORITHM = "AES";
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//默认的加密算法

    /**
     * AES 加密操作
     *
     * @param content 待加密内容
     * @param password 加密密码
     * @return 返回Base64转码后的加密数据
     */
    public static String encrypt(String content, String password) {
        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器

            byte[] byteContent = content.getBytes("utf-8");

            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化为加密模式的密码器

            byte[] result = cipher.doFinal(byteContent);// 加密

            return Base64.encodeBase64String(result);//通过Base64转码返回
        } catch (Exception ex) {
            Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    /**
     * AES 解密操作
     *
     * @param content
     * @param password
     * @return
     */
    public static String decrypt(String content, String password) {

        try {
            //实例化
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);

            //使用密钥初始化,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));

            //执行操作
            byte[] result = cipher.doFinal(Base64.decodeBase64(content));

            return new String(result, "utf-8");
        } catch (Exception ex) {
            Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }



    /**
     * AES 加密操作
     *
     * @param byteContent 待加密内容
     * @param password 加密密码
     * @return 加密字符串
     */
    public static byte[] encryptbyte(byte[] byteContent, byte[] password) {
        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器
            String spwd = new String(password);
            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(spwd));// 初始化为加密模式的密码器
            byte[] result = cipher.doFinal(byteContent);// 加密
            return  result;
        } catch (Exception ex) {
            Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    /**
     * AES 解密操作
     *
     * @param byteContent
     * @param password
     * @return 解密字符串
     */
    public static byte[] decryptByte(byte[] byteContent, byte[] password) {

        try {
            //实例化
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            String pwd = new String(password);
            //使用密钥初始化,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(pwd));
            //执行操作
            byte[] result = cipher.doFinal(byteContent);
            return result;
        } catch (Exception ex) {
            Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    /**
     * 生成加密秘钥
     *
     * @return
     */
    private static SecretKeySpec getSecretKey(final String password) {
        //返回生成指定算法密钥生成器的 KeyGenerator 对象
        KeyGenerator kg = null;

        try {
            kg = KeyGenerator.getInstance(KEY_ALGORITHM);

            //AES 要求密钥长度为 128
            kg.init(128, new SecureRandom(password.getBytes()));

            //生成一个密钥
            SecretKey secretKey = kg.generateKey();

            return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    public static void main(String[] args) {
        String s = "789helloWORLD{name:“信息”}";

        System.out.println("s:" + s);

//        String s1 = AESUtil.encrypt(s, "1234");
//        System.out.println("s1:" + s1);
//
//        System.out.println("s2:"+AESUtil.decrypt(s1, "1234"));


    try {
        byte[] pwd = AESUtil.encryptbyte(s.getBytes("UTF-8"), "1234".getBytes("utf-8"));
        System.out.println(new String(Base64.encodeBase64(pwd)));
        byte[] oldPwd = AESUtil.decryptByte(pwd,"1234".getBytes("UTF-8"));
        System.out.println(new String(oldPwd,"UTF-8"));

    }catch (Exception e){
        e.printStackTrace();
    }



    }

}


3.实现RedisSerializer接口:

package com.tms.bean.system.client;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.tms.bean.system.util.AESUtil;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.util.Assert;

import java.nio.charset.Charset;

/**
* Created by gjp on 2017/10/11.
*
*/
public class Jackson2JsonRedisSerializerAes<T> implements RedisSerializer<T> {

    private static final String PWD = "123456789asdfghjkl";

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    private final JavaType javaType;
    private ObjectMapper objectMapper = new ObjectMapper();

    public Jackson2JsonRedisSerializerAes(Class<T> type) {
        this.javaType = this.getJavaType(type);
    }

    public Jackson2JsonRedisSerializerAes(JavaType javaType) {
        this.javaType = javaType;
    }

    public T deserialize(byte[] bytes) throws SerializationException {
        if(null == bytes || bytes.length ==0) {
            return null;
        } else {
            try {
               byte[] result = AESUtil.decryptByte(bytes,PWD.getBytes(DEFAULT_CHARSET));

                return this.objectMapper.readValue(result, 0, bytes.length, this.javaType);
            } catch (Exception var3) {
                throw new SerializationException("Could not read JSON: " + var3.getMessage(), var3);
            }
        }
    }

    public byte[] serialize(Object t) throws SerializationException {
        if(t == null) {
            return new byte[0];
        } else {
            try {
                 byte[] temp = this.objectMapper.writeValueAsBytes(t);

                return AESUtil.encryptbyte(temp,PWD.getBytes(DEFAULT_CHARSET));
                //return this.objectMapper.writeValueAsBytes(t);
            } catch (Exception var3) {
                throw new SerializationException("Could not write JSON: " + var3.getMessage(), var3);
            }
        }
    }

    public void setObjectMapper(ObjectMapper objectMapper) {
        Assert.notNull(objectMapper, "'objectMapper' must not be null");
        this.objectMapper = objectMapper;
    }

    protected JavaType getJavaType(Class<?> clazz) {
        return TypeFactory.defaultInstance().constructType(clazz);
    }
}




没有加密时实现为:




加密后显示:





猜你喜欢

转载自gjp014.iteye.com/blog/2395881