这里有新鲜出炉的 Java 并发编程示例,程序狗速度看过来!
java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称。
本文主要介绍了 Java 敏感信息加密处理的相关知识:1)敏感信息加密处理我们要实现什么;2)敏感信息加密处理我做了些什么;3)敏感信息加密实现方法。具有很好的参考价值,下面跟着小编一起来看下吧
一、敏感信息加密处理我们要实现什么
系统往往需要将用户敏感信息进行加密,不同的敏感信息加密要求不同。
比如,密码的加密,我们往往不需要是可逆的。用户输入密码后,通过系统的加密规则,编码后直接比对加密存储的密码,获得比对结果即可证明用户登录信息合法性。
然后,有时我们为了防止被脱库导致的数据泄漏,不得不对一些敏感信息(比如:身份证号、手机号)进行加密。这样的数据不仅要求加密,还需要在展示及其他业务场景下完全显示,或者掩码显示,这就需要我们对加密的内容进行解密。
二、敏感信息加密处理我做了些什么
近来,项目中为了实现这个需求,做了些简单的设计:
注:考虑到在维护生产数据时方便查询,这里使用 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
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持 PHPERZ!
来源: http://www.phperz.com/article/17/1224/357943.html