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);
}
}


没有加密时实现为:


[img]http://dl2.iteye.com/upload/attachment/0127/3215/0900de11-188b-3e09-9ec2-00b083c92a7e.png[/img]

加密后显示:


[img]http://dl2.iteye.com/upload/attachment/0127/3217/fc4b4157-46c8-30a5-9e7e-a9dbf09f2431.png[/img]
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值