在Shiro中,登录操作是由Subject的login()方法完成的,Subject是个接口,在Web环境中,实现类为WebDelegatingSubject,login方法从DeletatingSubject继承而来:
public void login(AuthenticationToken token) throws AuthenticationException {
clearRunAsIdentitiesInternal();
Subject subject = securityManager.login(this, token);
// 省略一些代码...
}
由上可见,Subject.login()方法委托给了SecurityManager对象,在Web环境中,SecurityManager实现类为DefaultWebSecurityManager,其login方法从DefaultSecurityManager继承而来:
public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo info;
try {
// 对提交的AuthenticationToken进行认证
info = authenticate(token);
} catch (AuthenticationException ae) {
try {
// 如果认证失败
onFailedLogin(token, ae, subject);
} catch (Exception e) {
if (log.isInfoEnabled()) {
log.info("onFailedLogin method threw an " +
"exception. Logging and propagating original AuthenticationException.", e);
}
}
throw ae; //propagate,如果认证失败,使异常继续向上传播,从而返回至登录页面(见上篇)
}
// 如果认证成功则重新创建Subject对象
Subject loggedIn = createSubject(token, info, subject);
// 登录成功,主要处理RememberMe操作,即将登录信息存储在cookie中
onSuccessfulLogin(token, info, loggedIn);
return loggedIn;
}
最关键的authenticate方法:
public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {
return this.authenticator.authenticate(token);
}
SecurityManager把认证方法委托给认证器