认证最常见的形式及用户名密码登录。
一、 认证流程:
1. 首先调用Subject.login(AuthenticationToken)进行登录,其会自动委托给SecutityManager;
2.org.apache.shiro.mgt.SecurityManager(安全管理员)负责真正的身份验证逻辑,它会委托Authenticator进行身份验证;
3.Authenticator才是真正的身份验证者,Shiro API中核心的身份认证入口点,此处可以自定义插入自己的实现;
4.Authenticator可能会委托给相应的AuthenticationStategy进行多Realm身份验证,默认ModularRealmAuthorizer会调用AuthenticationStategy进行多个Realm身份验证;
5.Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,如果没有返回/抛出异常,表示身份验证失败;此处可以配置多个Realm,将按照相应的顺序以策略进行访问;
// 获取当前的 Subject. 调用 SecurityUtils.getSubject();
Subject currentUser = SecurityUtils.getSubject();
// 测试当前的用户是否已经被认证. 即是否已经登录.
// 调动 Subject 的 isAuthenticated()
if (!currentUser.isAuthenticated()) {
// 把用户名和密码封装为 UsernamePasswordToken 对象
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
// rememberme(记住我)
token.setRememberMe(true);
try {
// 执行登录.
currentUser.login(token);
}
// 若没有指定的账户, 则 shiro 将会抛出 UnknownAccountException 异常.
catch (UnknownAccountException uae) {
log.info("----> There is no user with username of " + token.getPrincipal());
return;
}
// 若账户存在, 但密码不匹配, 则 shiro 会抛出 IncorrectCredentialsException 异常。
catch (IncorrectCredentialsException ice) {
log.info("----> Password for account " + token.getPrincipal() + " was incorrect!");
return;
}
// 用户被锁定的异常 LockedAccountException
catch (LockedAccountException lae) {
log.info("The account for username " + token.getPrincipal() + " is locked. " +
"Please contact your administrator to unlock it.");
}// 所有认证时异常的父类.
catch (AuthenticationException ae) {
//unexpected condition? error?
}
}
二、认证异常:
1. org.apache.shiro.authc.AuthenticationException :认证异常
|- org.apache.shiro.authc.UnknownAccountException:没有指定的账户异常
|- org.apache.shiro.authc.IncorrectCredentialsException :不正确的密码异常
|- org.apache.shiro.authc.LockedAccountException:账户锁定异常
三、Realm:安全验证信息来源
1. org.apache.shiro.realm.Realm接口:
Shiro从Realm获取安全数据(如:角色、用户、权限),即SecutityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较,确定是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否可以进行操作;
String getName(); //返回唯一的Realm名称 boolean supports(AuthenticationToken token); //判断此 Realm是否支持Token AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException; //根据Token获取认证信息
2. org.apache.shiro.realm.AuthorizingRealm实现类:授权Realm
一般基层AuthorizingRealm(授权)即可;其继承了AuthenticatingRealm(身份验证),而且也间接继承了CachingRealm(带缓存实现);
四、验证器:进行验证
1. org.apache.shiro.authc.Authenticator接口:验证器
》单个Realm验证:Authenticator的职责是验证用户账号,是Shiro API中身份验证核心的入口点:如果验证成功,则返回“org.apache.shiro.authc.AuthenticationInfo”验证信息,此信息中包含了身份及凭证;如果验证失败则抛出AuthenticationException认证异常。
》多个Realm验证:org.apache.shiro.mgt.SecurityManager接口继承了Authenticator接口,另外还有一个“org.apache.shiro.authc.pam.ModularRealmAuthenticator”实现,其委托多个Realm进行验证,验证规则通过AuthenticationStrategy接口指定。
//Authenticator方法
public AuthenticationInfo authenticate(AuthenticationToken authenticationToken) throws AuthenticationException; //进行验证
2. org.apache.shiro.authc.AuthenticationInfo接口:身份验证信息
public Object getCredentials(); //获取凭据 public PrincipalCollection getPrincipals(); //获取相关的主体
五、token:令牌,用户提交的信息
1. org.apache.shiro.authc.AuthenticationToken接口:用于收集用户提交的身份(如用户名)及凭据(如密码)
public Object getPrincipal(); //获取用户名 public Object getCredentials(); //获取认证信息(密码),返回字符数组
|- org.apache.shiro.authc.UsernamePasswordToken实现类:用户名和密码令牌
public String getUsername(); //获取用户名 public char[] getPassword(); //获取密码 public void setRememberMe(boolean rememberMe); //记住我 public boolean isRememberMe(); //获取记住我
六、Subject:主题,用户的行为
org.apache.shiro.subject.Subject:代表着用户,用户所拥有的行为包括:登录、退出、校验权限、获得Session等,符合面向对象,任何与系统交互的行为都可以由Subject完成。
SecurityUtils.getSubject(); //获取当前正在执行的subject
//认证方法
public Object getPrincipal(); //获取登录id,如果没有则返回null(尚未登录) public Session getSession(); //获取Session public Session getSession(boolean create); //创建Sessoion public boolean isAuthenticated(); //是否通过认证 public boolean isRemembered(); //是否使用记住我 public void login(AuthenticationToken token) throws AuthenticationException; //登录 public void logout(); //注销