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