Subject
第一步:获取用户名(Principal)和密码(Credential);
//获取当前的Subject
UsernamePassworkToken token = new UsernamePassworkToken (username,password);
//Rmember me功能
.token.setRememberMe(true)
- AuthenticationToken接口:用于表示用户提交的用户名和密码的接口
- 通常使用UsernamePassworkToken类(派生自AuthenticationToken)进行认证。
用户是如何获取数据的与AuthenticationToken无关,可以从HTML表单、数据库、命令行和其他任何地方。
第二步:提交用户名和密码去验证
//获取当前的Subject
Subject user = SecurityUtils.getSubject();
// 用户尝试认证
user.login(token);
第三步:如果提交成功,认证成功,否则认证失败
//获取当前的Subject
try {
user.login(token);
} catch ( UnknownAccountException uae ) { ...
} catch ( IncorrectCredentialsException ice ) { ...
} catch ( LockedAccountException lae ) { ...
} catch ( ExcessiveAttemptsException eae ) { ...
} ... 捕获自定义AuthenticationException异常 ...
} catch ( AuthenticationException ae ) {
//未知错误
}
//程序正常,继续执行 ...
AuthenticationException异常
常见异常子类:
UnknownAccountException:用户名不存在
IncorrectCredentialsException:密码错误
LockedAccountException:账号被锁定
ExcessiveAttemptsException:账号在一段时间内尝试登录次数过多
认证流程
第一步:调用Subject.login(token),token是AuthenticationToken的实例。
第二步:Subject的子类DelegatingSubject调用securityManager.login来把认证任务交给SecurityManager
第三步:SecurityManger的子类DefaultSecurityManager使用从AuthenticatingSecurityManager继承来的成员authenticator的authenticate方法进行认证。
接下来看看Authenticator接口,其下的authenticate用于认证。
AbstractAuthenticator调用子类的doAuthenticate来执行真正的认证过程,这里子类只有ModularRealmAuthenticator,最终的认证由ModularRealmAuthenticator的doAuthenticate来执行。
ModularRealmAuthenticator
- 关键方法:doAuthenticate
- 流程:判断是单个realm认证还是多realm认证,分别调用doSingleRealmAuthentication,doMultiRealmAuthentication
调用doSingleRealmAuthentication
- 首先判断这个Realm是否支持提交的token类型,然后调用我们自己的Realm重写的的getAuthenticationInfo方法,返回包装了用户信息的AuthenticationInfo。
Realm
- 作用:简而言之,Realm就是一个安全相关的DAO。他的作用是读取数据源(数据库、文件)的数据转换为Realm能理解的数据(AuthenticationInfo)。
- 功能:执行认证和授权
判断是否支持AuthenticationToken
Realm需要判断传入的token类型是否是能够处理的。比如一个处理指纹认证的Realm就不能接收UsernamePasswordToken。
处理AuthenticationToken
- 从token取得用户身份信息(Principle)
- 根据用户身份,在数据源(数据库、文件)中查找对应的数据(体现了Realm本质是一个安全相关的DAO)
- 将toeken中提供的密码(credentials)与数据源取出来的密码相匹配
- 如果匹配,返回一个封装了数据源中用户数据(安全、权限等)的AuthenticationInfo,如果不匹配返回一个AnthenticationException。