一、敏感信息加密处理我们要实现什么

系统往往需要将用户敏感信息进行加密,不同的敏感信息加密要求不同。
比如,密码的加密,我们往往不需要是可逆的。用户输入密码后,通过系统的加密规则,编码后直接比对加密存储的密码,获得比对结果即可证明用户登录信息合法性。
然后,有时我们为了防止被脱库导致的数据泄漏,不得不对一些敏感信息(比如:身份证号、手机号)进行加密。这样的数据不仅要求加密,还需要在展示及其他业务场景下完全显示,或者掩码显示,这就需要我们对加密的内容进行解密。
二、敏感信息加密处理我做了些什么
近来,项目中为了实现这个需求,做了些简单的设计:
注:考虑到在维护生产数据时方便查询,这里使用aes加密方式,该加密方式同mysql的aes加密结果相同,故可在sql中直接使用hex及aes_encrypt函数进行查询;密盐可保存在配置文件中。
1.使用自定义注解,po的每个类中需要加密及解密的字段可添加该注解
2.声明Base类,并实现encrypt和decrypt方法,方法实现利用java反射及自定义注解
3.所有需要用到加密及解密的实体对象,必须继承自Base类
4.实体类加密时调用encrypt方法,解密时调用decrypt方法,如此可实现对该对象中敏感数据的加密解密
三、敏感信息加密实现
1.先看效果
注释很清楚,先给对象设置身份证号,然后执行自加密方法,返回自己的引用,打印出来加密后该对象的json字符串;执行自解密方法,返回自己的引用,打印出来解密后该对象的json字符串。
2.设计实现结构
crypt | |--annotation | |--DecryptFiled | |--EncryptFiled |--crypt | |--EncryptDecryptInterface |--domain | |--BaseInfo | |--SimpleDomain |--utils | |--MySqlUtils
2.1先看看注解的实现
/**
* Created by bright on 2017/2/22.
*
* @author :
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EncryptFiled {
String value() default "";
}
自定义注解
两个注解的实现一致,注解名称不同而已,不再贴另外一个注解的代码。
2.2定义自加密、自解密接口
Base类实现该接口中的自加密自解密方法
/**
* Created by bright on 2017/2/22.
*
* @author :
*/
public interface EncryptDecryptInterface {
public <T> T encryptSelf();
public <T> T decryptSelf();
}
自定义接口
2.3MysqlUtils的实现
/**
* Created by bright on 2017/2/22.
*
* @author :
*/
@Component
public class MySqlUtils {
private static final String ENCRYPTTYPE= "AES";//加密方式
private static final String ENCODING = "UTF-8";//加密时编码
private static String MYSQLUTILSKEY = "aaa";//加密密盐
private static MySqlUtils mysqlUtils;//单例
private static Cipher encryptCipher ;//加密cipher
private static Cipher decryptChipher;//解密chipher
/**
* 该方法可用在spring项目中使用配置文件设置密盐,默认值为123
* @param key
*/
@Value("${mysql.column.crypt.key:123}")
public void setMysqlutilskey(String key){
MySqlUtils.MYSQLUTILSKEY = key;
}
/**
* encryptCipher、decryptChipher初始化
*/
public static void init(){
try {
encryptCipher = Cipher.getInstance(ENCRYPTTYPE);
decryptChipher = Cipher.getInstance(ENCRYPTTYPE);
encryptCipher.init(Cipher.ENCRYPT_MODE, generateMySQLAESKey(MYSQLUTILSKEY, ENCODING));
decryptChipher.init(Cipher.DECRYPT_MODE, generateMySQLAESKey(MYSQLUTILSKEY, ENCODING));
} catch (InvalidKeyException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(e);
}
}
/**
* 单例获取方法实现
* @return
*/
public synchronized static MySqlUtils getInstance(){
if(mysqlUtils == null){
mysqlUtils = new MySqlUtils();
init();
}
return mysqlUtils;
}
/**
* 加密算法
* @param encryptString
* @return
*/
public String mysqlAESEncrypt(String encryptString) {
try{
return new String(Hex.encodeHex(encryptCipher.doFinal(encryptString.getBytes(ENCODING)))).toUpperCase();
} catch (BadPaddingException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
}
}
/**
* 解密算法
* @param decryptString
* @return
*/
public String mysqlAESDecrypt(String decryptString){
try {
return new String(decryptChipher.doFinal(Hex.decodeHex(decryptString.toCharArray())));
} catch (DecoderException nspe) {
throw new RuntimeException(nspe);
} catch (BadPaddingException nsae) {
throw new RuntimeException(nsae);
} catch (IllegalBlockSizeException ike) {
throw new RuntimeException(ike);
}
}
/**
* 产生mysql-aes_encrypt
* @param key 加密的密盐
* @param encoding 编码
* @return
*/
public static SecretKeySpec generateMySQLAESKey(final String key, final String encoding) {
try {
final byte[] finalKey = new byte[16];
int i = 0;
for(byte b : key.getBytes(encoding))
finalKey[i++%16] ^= b;
return new SecretKeySpec(finalKey, "AES");
} catch(UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
MysqlUtils
2.4BaseInfo类的实现
/**
* Created by bright on 2017/2/22.
*
* @author :
*/
public class BaseInfo implements Cloneable, EncryptDecryptInterface {
/**
* 拷贝一个对象,并对新对象进行加密
* 该方法主要用在日志打印上,可防止原对象被加密而影响程序执行
* @param <T>
* @return
*/
public <T extends BaseInfo> T cloneAndEncrypt() {
T cloneT = null;
try {
cloneT = (T) this.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
if(cloneT !=null)
return cloneT.encryptSelf();
throw new RuntimeException("拷贝对象异常");
}
/**
* 重写clone方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
/**
* 实现自加密
*
* @param <T>
* @return
*/
public <T> T encryptSelf() {
Field[] declaredFields = this.getClass().getDeclaredFields();
try {
if (declaredFields != null && declaredFields.length > 0) {
for (Field field : declaredFields) {
if (field.isAnnotationPresent(EncryptFiled.class) && field.getType().toString().endsWith("String")) {
field.setAccessible(true);
String fieldValue = (String) field.get(this);
if (StringUtils.isNotEmpty(fieldValue)) {
field.set(this, MySqlUtils.getInstance().mysqlAESEncrypt(fieldValue));
}
field.setAccessible(false);
}
}
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return (T) this;
}
/**
* 实现自解密
*
* @param <T>
* @return
*/
public <T> T decryptSelf() {
Field[] declaredFields = this.getClass().getDeclaredFields();
try {
if (declaredFields != null && declaredFields.length > 0) {
for (Field field : declaredFields) {
if (field.isAnnotationPresent(DecryptFiled.class) && field.getType().toString().endsWith("String")) {
field.setAccessible(true);
String fieldValue = (String)field.get(this);
if(StringUtils.isNotEmpty(fieldValue)) {
field.set(this, MySqlUtils.getInstance().mysqlAESDecrypt(fieldValue));
}
}
}
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return (T) this;
}
}
BaseInfo
2.5一个简单的对象
/**
* Created by bright on 2017/2/22.
*
* @author :
*/
public class SimpleDomain extends BaseInfo{
@EncryptFiled
@DecryptFiled
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
SimpleDomain
2.6来个调用
public class Client {
@Test
public void test(){
SimpleDomain sd = new SimpleDomain();//要进行加密解密的实体类
sd.setId("6029131988005021537");//注入身份证号
System.out.println(JSON.toJSONString(sd.encryptSelf()));//执行自加密后输出
System.out.println(JSON.toJSONString(sd.decryptSelf()));//执行自解密后输出
}
}
Client
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
# java
# 敏感信息加密
# 敏感信息处理
# JAVA简单实现MD5注册登录加密实例代码
# Android、iOS和Java通用的AES128加密解密示例代码
# JAVA 字符串加密、密码加密实现方法
# Java 对称加密几种算法分别实现
# 详解Java利用实现对称加密(DES、3DES、AES)
# java实现md5加密示例
# java常用工具类之DES和Base64加密解密类
# Java生成MD5加密字符串代码实例
# Java实现MD5加密及解密的代码实例分享
# 分享Java常用几种加密算法(四种)
# 自定义
# 自己的
# 时方
# 用在
# 配置文件
# 比对
# 打印出来
# 加密解密
# 些什么
# 要在
# 这就
# 可在
# 考虑到
# 实体类
# 重写
# 并对
# 很清楚
# 另外一个
# 不需
# 来个
相关文章:
建站之星在线版空间:自助建站+智能模板一键生成方案
ppt在线制作免费网站推荐,有什么下载免费的ppt模板网站?
香港服务器租用费用高吗?如何避免常见误区?
简历在线制作网站免费版,如何创建个人简历?
如何彻底删除建站之星生成的Banner?
如何快速搭建安全的FTP站点?
如何高效生成建站之星成品网站源码?
武汉网站如何制作,黄黄高铁武穴北站途经哪些村庄?
宝塔面板如何快速创建新站点?
七夕网站制作视频,七夕大促活动怎么报名?
如何在云服务器上快速搭建个人网站?
大连网站设计制作招聘信息,大连投诉网站有哪些?
如何用AWS免费套餐快速搭建高效网站?
网站制作外包价格怎么算,招聘网站上写的“外包”是什么意思?
小说建站VPS选用指南:性能对比、配置优化与建站方案解析
电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?
学校建站服务器如何选型才能满足性能需求?
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
山东云建站价格为何差异显著?
python的本地网站制作,如何创建本地站点?
如何在香港免费服务器上快速搭建网站?
历史网站制作软件,华为如何找回被删除的网站?
如何解决VPS建站LNMP环境配置常见问题?
建站之星后台搭建步骤解析:模板选择与产品管理实操指南
家具网站制作软件,家具厂怎么跑业务?
手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?
长沙企业网站制作哪家好,长沙水业集团官方网站?
如何快速打造个性化非模板自助建站?
如何通过虚拟主机空间快速建站?
海南网站制作公司有哪些,海口网是哪家的?
如何选择靠谱的建站公司加盟品牌?
建站之星代理如何获取技术支持?
企业宣传片制作网站有哪些,传媒公司怎么找企业宣传片项目?
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
建站之星免费版是否永久可用?
如何选择高性价比服务器搭建个人网站?
建站之星后台密码如何安全设置与找回?
宝塔建站助手安装配置与建站模板使用全流程解析
如何在云主机快速搭建网站站点?
php json中文编码为null的解决办法
定制建站流程步骤详解:一站式方案设计与开发指南
已有域名和空间,如何快速搭建网站?
建站中国必看指南:CMS建站系统+手机网站搭建核心技巧解析
如何规划企业建站流程的关键步骤?
如何快速生成橙子建站落地页链接?
制作网站的软件下载免费,今日头条开宝箱老是需要下载怎么回事?
如何获取上海专业网站定制建站电话?
制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?
c# Task.ConfigureAwait(true) 在什么场景下是必须的
如何通过虚拟主机快速完成网站搭建?
*请认真填写需求信息,我们会在24小时内与您取得联系。