異常內容:Authentication token of type [class org.apache.shiro.authc.UsernamePasswordToken] could not be authenticated by any configured realms. Please ensure that at least one realm can authenticate these tokens.
意思是沒有Realm進行處理,但實際上是當配置了多個realm時,就會 org.apache.shiro.authc.pam.ModularRealmAuthenticator#doMultiRealmAuthentication 通過這個方法進行執行,如果所有的對應的realm都返回認證異常或者null的話,就會出現以上錯誤
解決辦法
第一種 集成ModularRealmAuthenticator重寫doMultiRealmAuthentication方法
第二種,重寫Authenticator的認證策略,由於ModularRealmAuthenticator默認是配置的這個 AtLeastOneSuccessfulStrategy策略,那么重寫以下方法,當異常是認證異常時,則進行拋出認證異常
public class MyAtLeastOneSuccessfulStrategy extends AtLeastOneSuccessfulStrategy { @Override public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException { if(t instanceof AuthenticationException){ throw (AuthenticationException)t; } return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t); } public static void main(String[] args) { Provider[] providers = Security.getProviders(); System.out.println(providers); } }
根據所需拋出的異常時機,重寫以上方法即可,方法作用直接看doc就能明白
那么最關鍵的怎么配置呢?
這2個shiro的配置類,至少我這邊沒有使用上,如果你的代碼使用了,繼承此類重寫對應的方法返回的實例即可。
而我是這么解決的。
對應的Shiro的配置示例:
@Bean public SecurityManager securityManager(UserRealm userRealm, ApiAuthenticationRealm apiAuthenticationRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 設置realm. securityManager.setRealms(Arrays.asList(userRealm, apiAuthenticationRealm)); ...... Authenticator authenticator = securityManager.getAuthenticator(); if(authenticator instanceof ModularRealmAuthenticator){ ModularRealmAuthenticator modularRealmAuthenticator = (ModularRealmAuthenticator) authenticator; modularRealmAuthenticator.setAuthenticationStrategy(new MyAtLeastOneSuccessfulStrategy()); } // securityManager.setAuthenticator(); return securityManager; }