shiro教程3(加密)
加密,是以某種特殊的演算法改變原有的資訊資料,使得未授權的使用者即使獲得了已加密的資訊,但因不知解密的方法,仍然無法瞭解資訊的內容
概念
資料加密的基本過程就是對原來為明文的檔案或資料按某種演算法進行處理,使其成為不可讀的一段程式碼,通常稱為"密文",使其只能在輸入相應的金鑰之後才能顯示出本來內容,通過這樣的途徑來達到保護資料不被非法人竊取、閱讀的目的。
該過程的逆過程為==解密==,即將該編碼資訊轉化為其原來資料的過程。
加密分類
對稱加密
雙方使用的同一個金鑰,既可以加密又可以解密,這種加密方法稱為對稱加密,也稱為單金鑰加密。
非對稱加密
一對金鑰由公鑰和私鑰組成(可以使用很多對金鑰)。私鑰解密公鑰加密資料,公鑰解密私鑰加密資料(私鑰公鑰可以互相加密解密)。
加密演算法分類
單向加密
單向加密是==不可逆==的,也就是隻能加密,不能解密。通常用來傳輸類似使用者名稱和密碼,直接將加密後的資料提交到後臺,因為後臺不需要知道使用者名稱和密碼,可以直接將收到的加密後的資料儲存到資料庫
雙向加密
通常分為對稱性加密演算法和非對稱性加密演算法,對於對稱性加密演算法,資訊接收雙方都需事先知道密匙和加解密演算法且其密匙是相同的,之後便是對資料進行 加解密了。非對稱演算法與之不同,傳送雙方A,B事先均生成一堆密匙,然後A將自己的公有密匙傳送給B,B將自己的公有密匙傳送給A,如果A要給B傳送消 息,則先需要用B的公有密匙進行訊息加密,然後傳送給B端,此時B端再用自己的私有密匙進行訊息解密,B向A傳送訊息時為同樣的道理。
常見演算法
演算法 | 描述 |
---|---|
DES(Data Encryption Standard) | 資料加密標準,速度較快,適用於加密大量資料的場合; |
3DES(Triple DES) | 是基於DES,對一塊資料用三個不同的金鑰進行三次加密,強度更高; |
RC2和 RC4 | 用變長金鑰對大量資料進行加密,比 DES 快; |
IDEA(International Data Encryption Algorithm) | 國際資料加密演算法:使用 128 位金鑰提供非常強的安全性; |
RSA | 由 RSA 公司發明,是一個支援變長金鑰的公共金鑰演算法,需要加密的檔案塊的長度也是可變的; |
DSA(Digital Signature Algorithm) | 數字簽名演算法,是一種標準的 DSS(數字簽名標準); |
AES(Advanced Encryption Standard) | 高階加密標準,是下一代的加密演算法標準,速度快,安全級別高,目前 AES 標準的一個實現是 Rijndael 演算法; |
BLOWFISH | 它使用變長的金鑰,長度可達448位,執行速度很快; |
MD5 (Message-Digest Algorithm) | 訊息摘要演算法,一種被廣泛使用的密碼雜湊函式,可以產生出一個128位(16位元組)的雜湊值(hash value),用於確保資訊傳輸完整一致 |
MD5的使用
@Test public void Md5Test() { // 對單個資訊加密 Md5Hash md5 = new Md5Hash("123456"); System.out.println(md5.toString()); // 加密新增鹽值 增大解密難度 md5 = new Md5Hash("123456","aaa"); System.out.println(md5.toString()); // 加密新增鹽值 增大解密難度 2迭代兩次 md5 = new Md5Hash("123456","aaa",2); System.out.println(md5); }
輸出的結果:
e10adc3949ba59abbe56e057f20f883e 88316675d7882e3fdbe066000273842c a7cf41c6537065fe724cc9980f8b5635
鹽值的作用
使用MD5存在一個問題,相同的password生成的hash值是相同的,如果兩個使用者設定了相同的密碼,那麼資料庫中會儲存兩個相同的值,這是極不安全的,加Salt可以在一定程度上解決這一問題,所謂的加Salt方法,就是加點‘佐料’。其基本想法是這樣的,當用戶首次提供密碼時(通常是註冊時)由系統自動往這個密碼裡撒一些‘佐料’,然後在雜湊,而當用戶登入時,系統為使用者提供的程式碼上撒上相同的‘佐料’,然後雜湊,再比較雜湊值,來確定密碼是否正確。
加鹽的原理:
給原文加入隨機數生成新的MD5的值
shiro中使用MD5加密
認證方法中修改
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 獲取賬號資訊 String principal = (String) token.getPrincipal(); // 正常邏輯此處應該根據賬號去資料庫中查詢,此處我們預設賬號為 root 密碼123456 // 驗證賬號 if(!"root".equals(principal)){ // 賬號錯誤 return null; } //String pwd = "123456"; // 12345 根據 鹽值 aaa 加密獲取的密文 //88316675d7882e3fdbe066000273842c1次迭代的密文 //a7cf41c6537065fe724cc9980f8b56352次迭代的密文 String pwd = "88316675d7882e3fdbe066000273842c"; // 驗證密碼 AuthenticationInfo info = new SimpleAuthenticationInfo( principal, pwd,new SimpleByteSource("aaa"),"myrealm"); return info; }
ini.xml檔案修改
[main] #定義憑證匹配器 credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher #雜湊演算法 credentialsMatcher.hashAlgorithmName=md5 #雜湊次數 credentialsMatcher.hashIterations=1 #將憑證匹配器設定到realm customRealm=com.dpb.realm.MyRealm customRealm.credentialsMatcher=$credentialsMatcher securityManager.realms=$customRealm
測試
@Test public void test() { // 1.獲取SecurityManager工廠物件 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); // 2.通過Factory物件獲取SecurityManager物件 SecurityManager securityManager = factory.getInstance(); // 3.將SecurityManager物件新增到當前執行環境中 SecurityUtils.setSecurityManager(securityManager); // 4.獲取Subject物件 Subject subject = SecurityUtils.getSubject(); AuthenticationToken token = new UsernamePasswordToken("root", "123456"); // 登入操作 try { subject.login(token); } catch (UnknownAccountException e) { System.out.println("賬號出錯..."); } catch(IncorrectCredentialsException e){ System.out.println("密碼出錯..."); } // 獲取登入的狀態 System.out.println(subject.isAuthenticated()); }
迭代1次
迭代兩次