今天比較晚,所以只看了shiro的認證策略Authentication Strategy,下麵講講shiro的三種認證策略。 1.AtLeastOneSuccessfulStrategy:這個是shiro預設的認證策略,它表示如果存在多個realm來執行認證,只要其中有一個成功,那麼認證就成功(這裡 ...
今天比較晚,所以只看了shiro的認證策略Authentication Strategy,下麵講講shiro的三種認證策略。
1.AtLeastOneSuccessfulStrategy:這個是shiro預設的認證策略,它表示如果存在多個realm來執行認證,只要其中有一個成功,那麼認證就成功(這裡註意所有的realm都會進行驗證,不管是失敗還是成功);
2.AllSuccessfulStrategy:這個策略表示必須所有的realm認證成功才算最終認證成功,哪怕只有一個不成功,那麼結果都為認證不成功。(這裡也是會將所有的realm都進行驗證);
3.FirstSuccessfulStrategy:它表示只要有一個realm中認證成功了,那麼剩下的其它realm都不必進行驗證了,直接返回認證成功。註意這裡只要遇到第一個成功認證的realm,其他剩下的realm都不會被調用。
說了三種認證策略的概念,那麼我們怎麼進行配置認證策略呢?這個問題就要追溯到shiro中進行認證操作的認證器子類modularRealmAuthenticator,它裡面有一個屬性authenticationStrategy,並且
modularRealmAuthenticator在它的構造函數中將這個屬性預設設置成new AtLeastOneSuccessfulStrategy():
private AuthenticationStrategy authenticationStrategy; /*-------------------------------------------- | C O N S T R U C T O R S | ============================================*/ /** * Default no-argument constructor which * {@link #setAuthenticationStrategy(AuthenticationStrategy) enables} an * {@link org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy} by default. */ public ModularRealmAuthenticator() { this.authenticationStrategy = new AtLeastOneSuccessfulStrategy(); }
所有我們要配置認證策略,只需要配置modularRealmAuthenticator類中的authenticationStrategy屬性。下麵是配置認證策略的過程:
[main] dataSource=com.mchange.v2.c3p0.ComboPooledDataSource dataSource.driverClass=com.mysql.jdbc.Driver dataSource.jdbcUrl=jdbc:mysql://localhost:3306/test dataSource.user=root dataSource.password=root myRealm=org.apache.shiro.realm.jdbc.JdbcRealm myRealm.dataSource=$dataSource dataSource1=com.mchange.v2.c3p0.ComboPooledDataSource dataSource1.driverClass=com.mysql.jdbc.Driver dataSource1.jdbcUrl=jdbc:mysql://localhost:3306/test1 dataSource1.user=root dataSource1.password=root myRealm1=org.apache.shiro.realm.jdbc.JdbcRealm myRealm1.dataSource=$dataSource1 #配置認證策略 authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator authenticationStrategy=org.apache.shiro.authc.pam.FirstSuccessfulStrategy authenticator.authenticationStrategy=$authenticationStrategy securityManager.authenticator=$authenticator securityManager.realms=$myRealm,$myRealm1
在配置認證策略中,我將認證策略配成了FirstSuccessFulStrategy,然後將這個配置了新的認證策略的認證器賦予了SecurityManager中的authenticator屬性從而完成了認證策略的配置。為了測試這幾個策略的區別,我在shiro.ini文件中又創建了一個realm,並註入了一個新的數據源:
兩個資料庫中都有users的表,但是數據並不相同。下麵開始認證編碼,還是那一套流程:
package test_JdbcRealm; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestAuthencationStrategy { private static final Logger logger = LoggerFactory.getLogger(TestAuthencationStrategy.class); public static void main(String[] args) { //1.創建securityManager工廠 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); //2.獲取securityManager實例 SecurityManager securityManager = factory.getInstance(); //3.將SecurityManager實例設置到SecurityUtils工具類中 SecurityUtils.setSecurityManager(securityManager); //4。創建Subject實例 Subject subject = SecurityUtils.getSubject(); //5.獲取token,模擬用戶登陸 UsernamePasswordToken token = new UsernamePasswordToken("wangwu", "456789"); try { //6.認證token subject.login(token); if(subject.isAuthenticated()) { logger.info("登陸成功"); } } catch (AuthenticationException e) { // TODO Auto-generated catch block e.printStackTrace(); logger.error("用戶名或密碼錯誤,登陸失敗"); } } }
運行控制台輸出如下:
2019-07-26 23:54:32,756 INFO [com.mchange.v2.log.MLog] - MLog clients using slf4j logging. 2019-07-26 23:54:33,216 INFO [com.mchange.v2.c3p0.C3P0Registry] - Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10] 2019-07-26 23:54:33,344 INFO [org.apache.shiro.config.IniSecurityManagerFactory] - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur. 2019-07-26 23:54:33,373 INFO [com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource] - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 2zm2h7a4d1dnn281ezvn|7e0ea639, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2zm2h7a4d1dnn281ezvn|7e0ea639, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/test, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ] 2019-07-26 23:54:33,677 INFO [com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource] - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 2zm2h7a4d1dnn281ezvn|6e1567f1, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2zm2h7a4d1dnn281ezvn|6e1567f1, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/test1, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ] 2019-07-26 23:54:33,696 INFO [org.apache.shiro.session.mgt.AbstractValidatingSessionManager] - Enabling session validation scheduler... 2019-07-26 23:54:33,704 INFO [test_JdbcRealm.TestAuthencationStrategy] - 登陸成功
可以看到雖然test資料庫中沒有wangwu這個用戶,但是test1資料庫中有,所以myRealm1的認證過程是成功了的,而myRealm的認證過程毋庸置疑是失敗了的,但是我們這裡配的認證策略是FirstSuccessfulStrategy,所以只要有一個成功,就認證成功。
我們把認證策略改成AllSuccessfulStrategy再來測試一下上面的認證流程,發現控制台輸出瞭如下內容:
2019-07-26 23:59:26,933 INFO [com.mchange.v2.log.MLog] - MLog clients using slf4j logging. 2019-07-26 23:59:27,323 INFO [com.mchange.v2.c3p0.C3P0Registry] - Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10] 2019-07-26 23:59:27,447 INFO [org.apache.shiro.config.IniSecurityManagerFactory] - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur. 2019-07-26 23:59:27,476 INFO [com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource] - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 2zm2h7a4d1jymk14v9ac3|7e0ea639, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2zm2h7a4d1jymk14v9ac3|7e0ea639, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/test, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ] org.apache.shiro.authc.UnknownAccountException: No account found for user [wangwu] at org.apache.shiro.realm.jdbc.JdbcRealm.doGetAuthenticationInfo(JdbcRealm.java:244) 2019-07-26 23:59:27,761 ERROR [test_JdbcRealm.TestAuthencationStrategy] - 用戶名或密碼錯誤,登陸失敗 at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:571) at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doMultiRealmAuthentication(ModularRealmAuthenticator.java:219) at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:269) at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198) at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106) at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:275) at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260) at test_JdbcRealm.TestAuthencationStrategy.main(TestAuthencationStrategy.java:30)
報了用戶找不到的異常,因為在test資料庫中我們並沒有wangwu這個用戶,所以myRealm認證是失敗的,而我們配置了AllSuccessfulStrategy這個策略,只要有一個認證失敗,那麼最終就認證失敗,因此這裡輸出了認證失敗的提示語。
以上是我今天所看的shiro認證策略的內容和應用,如果有什麼糾正和補充的請在評論區留言,謝謝!