常用加密方式如哈希、對稱、非對稱,而想要自定義加密方式,就得了解shiro是如何對令牌進行匹配的。
1.普通匹配
密碼校驗等相關操作,在shiro中是屬於Realm的功能,自定的Realm繼承org.apache.shiro.realm.AuthorizingRealm類,實現了org.apache.shiro.realm.AuthorizingRealm.doGetAuthorizationInfo和org.apache.shiro.realm.AuthenticatingRealm.doGetAuthenticationInfo這兩個抽象方法。它們之間的關係如下:
doGetAuthorizationInfo這個方法是獲取授權內容的方法,因此在令牌認證部分與它無關,所以這裏着重看doGetAuthenticationInfo這個方法以及它所在的父類。通過搜索AuthenticatingRealm類中的doGetAuthorizationInfo,可以看到一個getAuthenticationInfo的方法。該方法主要是用於,通過token去先進行緩存中獲取身份實例,如果緩存沒有,則進入我們自己實現的doGetAuthorizationInfo中去獲取實例,拿到實例後就進行令牌與身份實例的匹配驗證,即,執行assertCredentialsMatch這個方法。
assertCredentialsMatch這個方法的說明可知,它會去進行token和賬戶信息的匹配,匹配失敗的話就會拋出異常。
關鍵其實就在於這個憑據匹配器(CredentialsMatcher),token的驗證,或者結合一般的實際說,密碼的驗證,就是通過這個匹配器去做匹配。因此,只需要繼承匹配器的類去重寫裏面的方法,然後設置到Realm中即可。
源碼中,CredentialsMatcher是一個接口,只提供了一個doCredentialsMatch方法,而實現這個接口的就是org.apache.shiro.authc.credential.SimpleCredentialsMatcher。至於其他的Md和Sha的CredentialsMatcher是繼承於org.apache.shiro.authc.credential.HashedCredentialsMatcher的使用哈希方式加密的匹配器,HashedCredentialsMatcher又是繼承SimpleCredentialsMatcher的,這裏不進行深究。
protected Object getCredentials(AuthenticationToken token) {
return token.getCredentials();
}
protected Object getCredentials(AuthenticationInfo info) {
return info.getCredentials();
}
以上是獲取token中的密碼部分和info中的密碼部分,執行equals方法進行對比,而這裏並沒有進行什麼加密的處理。因此,我門只需重寫這部分即可。當然並不是必須的,可以通過其他方式,知道達到目標即可。
2.加密匹配
以MD5加密爲例,使用shiro自帶的加密方式進行加密後匹配,需要先在shiro基本配置類中聲明一個要使用的匹配器的Bean。
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");// 設置散列算法:MD5;
hashedCredentialsMatcher.setHashIterations(1024);// 設置散列次數
return hashedCredentialsMatcher;
}
然後在自定義的Realm中爲父類注入該匹配器。
@Autowired
public void setCredentialsMatcher(HashedCredentialsMatcher hashedCredentialsMatcher){
super.setCredentialsMatcher(hashedCredentialsMatcher);
}
而區別就在於,HashedCredentialsMatcher在doCredentialsMatch的時候會執行hashProvidedCredentials這個方法,這個方法最終就是進行MD5加密。
因此也可以在測試類中,自己new SimpleHash來進行加密測試。
3.重寫匹配器
新建一個類,繼承SimpleCredentialsMatcher,然後就可根據自己的需求重寫doCredentialsMatch這個方法即可,然後按加密匹配的方式,在shiroConfig類中聲明這個自定義匹配器的Bean,然後將這個匹配器在自定義Realm中注入到父類裏,那麼在進行shiro身份認證操作時,就會進入到這個類裏進行密碼/令牌的匹配了。
package com.gnz48.zzt....;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
public class CustomerCredentialsMatcher extends SimpleCredentialsMatcher {
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
/**
* 以下部分都可根據自己需要重寫
*/
Object tokenCredentials = getCredentials(token);
Object accountCredentials = getCredentials(info);
return equals(tokenCredentials, accountCredentials);
}
}