shiro密碼的比對,密碼的MD5加密,MD5鹽值加密,多個Relme
有具體問題的可以參考之前的關於shiro的博文,關於shiro的博文均是一次工程的內容
密碼的比對
通過AuthenticatingRealm的CredentialsMatcher方法
密碼的加密,主要是在CredentialsMatcher的....
密碼的MD5加密
資料表中儲存的密碼,不應該是明文的,而且不能反推得到密碼
1.如何把一個字串加密成MD5
使用其提供的介面實現
2.替換當前的Realm的CredentialsMatcher屬性,直接使用HashedCredentialsMatcher物件,
並且設定加密演算法
applicatonContext.xml檔案中
<!-- 3.配置Realm 3.1直接實現Realm介面的bean --> <bean id="jdbcRealm"class="com.MrChengs.shiro.realms.ShiroRealm"> <property name="credentialsMatcher"> <beanclass="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!-- 加密的方法 --> <property name="hashAlgorithmName"value="MD5"></property> <!-- 指定加密的次數 --> <property name="hashIterations"value="20"></property> </bean> </property> </bean>
看原始碼:
public SimpleHash(String algorithmName, Object source, Objectsalt, int hashIterations) throws CodecException, UnknownAlgorithmException { if (!StringUtils.hasText(algorithmName)) { throw new NullPointerException("algorithmNameargument cannot be null or empty."); } this.algorithmName = algorithmName; this.iterations = Math.max(DEFAULT_ITERATIONS,hashIterations); ByteSource saltBytes = null; if (salt != null) { saltBytes = convertSaltToBytes(salt); this.salt = saltBytes; } ByteSource sourceBytes = convertSourceToBytes(source); hash(sourceBytes, saltBytes, hashIterations); }
測試加密:
public static void main(String[] args) { String hash="MD5"; Object cred = "123456"; Object salt = null; int hashInter = 1024; //加密的類 System.out.println(new SimpleHash(hash, cred, salt,hashInter)); }
fc1709d0a95a6be30bc5926fdb7f22f4
MD5鹽值加密
假設兩個人原始密碼一致,這樣也會更加安全
所以此時需要使用到鹽值
步驟:
在 doGetAuthenticationInfo 的方法返回值建立 SimpleAuthenticationInfo 物件的時候
使用 SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
//鹽值 ByteSource credentialsSalt =ByteSource.Util.bytes(username);
使用ByteSource.Util.bytes()來計算鹽值
鹽值需要唯一一般使用隨機字串或userid
使用 new SimpleHash(algorithmName, source, salt, hashIterations) 計算鹽值解密後的鹽值
此時放置的不在是明文的密碼
ShiroRealm.java
//6.根據使用者的情況來構建AuthenticationInfo並且返回 //以下資訊是從資料庫中獲取的 //principal:認證的實體資訊,可以是username,也可以是資料表對應的實體物件 Object principal = username; //credentials:密碼 Object credentials = null; if("user".equals(username)){ //計算後user密碼為123456的鹽值 credentials ="2044dc18864ca3bc408359a0fb13c2a7"; }else if("admin".equals(username)){ //計算和admin密碼為123456的鹽值 credentials ="30beaf2a87d54ebe889cfccc076247ad"; } //realmName:當前realm物件為name,呼叫父類的getName()方法即可 String realmName = getName(); //鹽值 ByteSource credentialsSalt =ByteSource.Util.bytes(username); SimpleAuthenticationInfo info = null;//newSimpleAuthenticationInfo(principal, credentials, realmName); info = new SimpleAuthenticationInfo(principal,credentials, credentialsSalt, realmName); return info; }
鹽值的計算:
public static void main(String[] args) { String hash="MD5"; Object cred = "123456"; Object salt = "admin"; int hashInter = 20; //加密的類 System.out.println(new SimpleHash(hash, cred, salt,hashInter)); //new SimpleHash(algorithmName, source, salt,hashIterations) }
在測試中,只有使用者名稱為user/admin 密碼為123456才能成功登陸
多Realm
建立新的類
SecondRealm。java
public class SecondRealm extends AuthenticatingRealm { @Override protected AuthenticationInfodoGetAuthenticationInfo(AuthenticationToken arg0) throwsAuthenticationException { System.out.println("SecondRealm-->"); //1.把AuthenticationToken轉為UsernamePasswordToken UsernamePasswordTokenupToken =(UsernamePasswordToken) arg0; //2.從UsernamePasswordToken獲取username String username = upToken.getUsername(); //3.呼叫資料庫的方法,從資料庫查詢username對應的使用者記錄 System.out.println("從資料庫中獲取username:" +username); //4.若使用者不存在可以丟擲異常 UnKnownAccountException異常 if("unknow".equals(username)){ throw new UnknownAccountException("username 不存在"); } //5.根據使用者資訊的清空決定是否需要丟擲其他的異常 if("monster".equals(username)){ throw new LockedAccountException("使用者被鎖定"); } //6.根據使用者的情況來構建AuthenticationInfo並且返回 //以下資訊是從資料庫中獲取的 //principal:認證的實體資訊,可以是username,也可以是資料表對應的實體物件 Object principal = username; //credentials:密碼 Object credentials = null; if("user".equals(username)){ credentials ="6e3be0247455b9298f47eac8e57a07214ef84115"; }else if("admin".equals(username)){ credentials ="ff9633d047eaaf9861984ed86e5f73f904647716"; } //realmName:當前realm物件為name,呼叫父類的getName()方法即可 String realmName = getName(); //鹽值 ByteSource credentialsSalt =ByteSource.Util.bytes(username); SimpleAuthenticationInfo info = null;//newSimpleAuthenticationInfo(principal, credentials, realmName); info = new SimpleAuthenticationInfo(principal,credentials, credentialsSalt, realmName); return info; } public static void main(String[] args) { String hash="SHA1"; Object cred = "123456"; Object salt = "user"; int hashInter = 20; //加密的類 System.out.println(new SimpleHash(hash, cred, salt,hashInter)); //new SimpleHash(algorithmName, source, salt,hashIterations) } }
加密方式是SHA1
在applicationContext.xml
<!-- 1.配置SecurityManager --> <bean id="securityManager"class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="cacheManager" ref="cacheManager"/> <!--此時這個屬性需要註釋使用下面的屬性配置 <property name="realm" ref="jdbcRealm"/> --> <property name="authenticator"ref="autheniicator"></property> </bean>
<!-- 認證器 --> <bean id="autheniicator"class="org.apache.shiro.authc.pam.ModularRealmAuthenticator"> <property name="realms"> <list> <ref bean="jdbcRealm"/> <ref bean="SecondRealm"/> </list> </property> </bean> <!-- 3.配置Realm 3.1直接實現Realm介面的bean --> <bean id="jdbcRealm"class="com.MrChengs.shiro.realms.ShiroRealm"> <property name="credentialsMatcher"> <beanclass="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!-- 加密的方法 --> <property name="hashAlgorithmName"value="MD5"></property> <!-- 指定加密的次數 --> <property name="hashIterations"value="20"></property> </bean> </property> </bean> <bean id="SecondRealm"class="com.MrChengs.shiro.realms.SecondRealm"> <property name="credentialsMatcher"> <beanclass="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!-- 加密的方法 --> <property name="hashAlgorithmName"value="SHA1"></property> <!-- 指定加密的次數 --> <property name="hashIterations"value="20"></property> </bean> </property> </bean>
執行的順序和list的順序有關
<bean id="autheniicator"class="org.apache.shiro.authc.pam.ModularRealmAuthenticator"> <property name="realms"> <list> <ref bean="jdbcRealm"/> <ref bean="SecondRealm"/> </list> </property> </bean>