本文主要介紹了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
以上是Java敏感資訊加密處理的範例程式碼分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!