加密,是以某種特殊的算法改變原有的信息數據,使得未授權的用戶即使獲得了已加密的信息,但因不知解密的方法,仍然無法了解信息的內容
概念
數據加密的基本過程就是對原來為明文的文件或數據按某種算法進行處理,使其成為不可讀的一段代碼,通常稱為"密文",使其只能在輸入相應的密鑰之后才能顯示出本來內容,通過這樣的途徑來達到保護數據不被非法人竊取、閱讀的目的。
該過程的逆過程為解密,即將該編碼信息轉化為其原來數據的過程。
加密分類
對稱加密
雙方使用的同一個密鑰,既可以加密又可以解密,這種加密方法稱為對稱加密,也稱為單密鑰加密。
非對稱加密
一對密鑰由公鑰和私鑰組成(可以使用很多對密鑰)。私鑰解密公鑰加密數據,公鑰解密私鑰加密數據(私鑰公鑰可以互相加密解密)。
加密算法分類
單向加密
單向加密是不可逆的,也就是只能加密,不能解密。通常用來傳輸類似用戶名和密碼,直接將加密后的數據提交到后台,因為后台不需要知道用戶名和密碼,可以直接將收到的加密后的數據存儲到數據庫
雙向加密
通常分為對稱性加密算法和非對稱性加密算法,對於對稱性加密算法,信息接收雙方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是對數據進行 加解密了。非對稱算法與之不同,發送雙方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 加密獲取的密文
//88316675d7882e3fdbe066000273842c 1次迭代的密文
//a7cf41c6537065fe724cc9980f8b5635 2次迭代的密文
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次