shiro的主要配置是从SecurityManager配置,他的类图如下:
每个Manager都对应一个实现类进行真正的操作
从SecurityUtils.getSubject().login(token)
1. Subject 登录主题
对外定义了登录动作,以及登陆后的各种权限,角色的验证,默认实现类是DelegatingSubject
它内部持有一个SecurityManager类
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类
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接口,负责对外获取对应认证需要的信息,如用户、角色、权限等
具体实现如下:
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
具体
3、负责验证的类AuthorizingSecurityManager
SecurityManager的检查权限检查委托执行类就是它,而它内部有个
Authorizer authorizer类,最终执行需要它负责,进一步委托给AuthorizingRealm