shiro的主要配置是從SecurityManager配置,他的類圖以下:java
每一個Manager都對應一個實現類進行真正的操做session
從SecurityUtils.getSubject().login(token)app
1. Subject 登陸主題this
對外定義了登陸動做,以及登錄後的各類權限,角色的驗證,默認實現類是DelegatingSubjectspa
它內部持有一個SecurityManager類3d
protected transient SecurityManager securityManager;
//具體登陸動做以下
1. 經過 securityManager 的login方法進行登陸
2. 登陸成功後獲取到當前的session (Session session = subject.getSession(false);)
public void login(AuthenticationToken token) throws AuthenticationException {
this.clearRunAsIdentitiesInternal();
Subject subject = this.securityManager.login(this, token);
String host = null;
PrincipalCollection principals;
if (subject instanceof DelegatingSubject) {
DelegatingSubject delegating = (DelegatingSubject)subject;
principals = delegating.principals;
host = delegating.host;
} else {
principals = subject.getPrincipals();
}
if (principals != null && !principals.isEmpty()) {
this.principals = principals;
this.authenticated = true;
if (token instanceof HostAuthenticationToken) {
host = ((HostAuthenticationToken)token).getHost();
}
if (host != null) {
this.host = host;
}
Session session = subject.getSession(false);
if (session != null) {
this.session = this.decorate(session);
} else {
this.session = null;
}
} else {
String msg = "Principals returned from securityManager.login( token ) returned a null or empty value. This value must be non null and populated with one or more elements.";
throw new IllegalStateException(msg);
}
}
2. 負責登陸的SecurityManager類code
public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException { AuthenticationInfo info; try { //委託給父類的AuthorizingSecurityManager的authenticate方法去執行 info = this.authenticate(token); } catch (AuthenticationException var7) { AuthenticationException ae = var7; try { this.onFailedLogin(token, ae, subject); } catch (Exception var6) { if (log.isInfoEnabled()) { log.info("onFailedLogin method threw an exception. Logging and propagating original AuthenticationException.", var6); } } throw var7; } Subject loggedIn = this.createSubject(token, info, subject); this.onSuccessfulLogin(token, info, loggedIn); return loggedIn; }
認證接口 public interface Authenticator { AuthenticationInfo authenticate(AuthenticationToken var1) throws AuthenticationException; }
ModularRealmAuthenticator默認實現類
內部有Realm接口,負責對外獲取對應認證須要的信息,如用戶、角色、權限等blog
具體實現以下:token
protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) { if (!realm.supports(token)) { String msg = "Realm [" + realm + "] does not support authentication token [" + token + "]. Please ensure that the appropriate Realm implementation is " + "configured correctly or that the realm accepts AuthenticationTokens of this type."; throw new UnsupportedTokenException(msg); } //具體由realm的getAuthenticationIfo方法根據token去驗證身份,所以也是能夠擴展的地方 AuthenticationInfo info = realm.getAuthenticationInfo(token); //若是返回空則驗證失敗 if (info == null) { String msg = "Realm [" + realm + "] was unable to find account data for the " + "submitted AuthenticationToken [" + token + "]."; throw new UnknownAccountException(msg); } return info; }
而Realm默認實現類是接口
ModularRealmAuthenticator
具體
三、負責驗證的類AuthorizingSecurityManager
SecurityManager的檢查權限檢查委託執行類就是它,而它內部有個
Authorizer authorizer類,最終執行須要它負責,進一步委託給AuthorizingRealm