Apache Shiro 使用手册(二)Shiro 认证

1、Shiro认证过程 java

一、收集实体/凭据信息 apache

//Example using most common scenario of username/password pair:
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//”Remember Me” built-in:
token.setRememberMe(true);

UsernamePasswordToken支持最多见的用户名/密码的认证机制。同时,因为它实现了RememberMeAuthenticationToken接口,咱们能够经过令牌设置“记住我”的功能。session

可是,“已记住”和“已认证”是有区别的: 架构

已记住的用户仅仅是非匿名用户,你能够经过subject.getPrincipals()获取用户信息。可是它并不是是彻底认证经过的用户,当你访问须要认证用户的功能时,你仍然须要从新提交认证信息。 ide

这一区别能够参考亚马逊网站,网站会默认记住登陆的用户,再次访问网站时,对于非敏感的页面功能,页面上会显示记住的用户信息,可是当你访问网站帐户信息时仍然须要再次进行登陆认证。工具

二、提交实体/凭据信息 网站

Subject currentUser = SecurityUtils.getSubject();
currentUser.login(token);

收集了实体/凭据信息以后,咱们能够经过SecurityUtils工具类(1),获取当前的用户(2),而后经过调用login方法提交认证(3)。 ui

三、认证处理spa

try {
    currentUser.login(token);
} catch ( UnknownAccountException uae ) { ...
} catch ( IncorrectCredentialsException ice ) { ...
} catch ( LockedAccountException lae ) { ...
} catch ( ExcessiveAttemptsException eae ) { ...
} ... catch your own ...
} catch ( AuthenticationException ae ) {
    //unexpected error?
}

若是login方法执行完毕且没有抛出任何异常信息,那么便认为用户认证经过。以后在应用程序任意地方调用SecurityUtils.getSubject() 均可以获取到当前认证经过的用户实例,使用subject.isAuthenticated()判断用户是否已验证都将返回truecode

相反,若是login方法执行过程当中抛出异常,那么将认为认证失败。Shiro有着丰富的层次鲜明的异常类来描述认证失败的缘由,如代码示例。 

2、登出操做 

登出操做能够经过调用subject.logout()来删除你的登陆信息,如: 

//removes all identifying information and invalidates their session too.
currentUser.logout();

当执行完登出操做后,Session信息将被清空,subject将被视做为匿名用户。

3、认证内部处理机制

以上,是Shiro认证在应用程序中的处理过程,下面将详细解说Shiro认证的内部处理机制。

如上图,咱们经过Shiro架构图的认证部分,来讲明Shiro认证内部的处理顺序:

一、应用程序构建了一个终端用户认证信息的AuthenticationToken 实例后,调用Subject.login方法。 

二、Sbuject的实例一般是DelegatingSubject类(或子类)的实例对象,在认证开始时,会委托应用程序设置的securityManager实例调用securityManager.login(token)方法。 

三、SecurityManager接受到token(令牌)信息后会委托内置的Authenticator的实例(一般都是ModularRealmAuthenticator类的实例)调用authenticator.authenticate(token). ModularRealmAuthenticator在认证过程当中会对设置的一个或多个Realm实例进行适配,它实际上为Shiro提供了一个可拔插的认证机制。

四、若是在应用程序中配置了多个Realm,ModularRealmAuthenticator会根据配置的AuthenticationStrategy(认证策略)来进行多Realm的认证过程。在Realm被调用后,AuthenticationStrategy将对每个Realm的结果做出响应。 

注:若是应用程序中仅配置了一个Realm,Realm将被直接调用而无需再配置认证策略。

五、判断每个Realm是否支持提交的token,若是支持,Realm将调用getAuthenticationInfo(token); getAuthenticationInfo 方法就是实际认证处理,咱们经过覆盖Realm的doGetAuthenticationInfo方法来编写咱们自定义的认证处理。 

4、使用多个Realm的处理机制:

一、Authenticator 
默认实现是ModularRealmAuthenticator,它既支持单一Realm也支持多个Realm。若是仅配置了一个Realm,ModularRealmAuthenticator 会直接调用该Realm处理认证信息,若是配置了多个Realm,它会根据认证策略来适配Realm,找到合适的Realm执行认证信息。 

自定义Authenticator的配置:

[main]
...
authenticator = com.foo.bar.CustomAuthenticator
securityManager.authenticator = $authenticator

二、AuthenticationStrategy(认证策略)

  1. 当应用程序配置了多个Realm时,ModularRealmAuthenticator将根据认证策略来判断认证成功或是失败。 
    例如,若是只有一个Realm验证成功,而其余Realm验证失败,那么此次认证是否成功呢?

  2. 若是大多数的Realm验证成功了,认证是否就认为成功呢?

  3. 或者,一个Realm验证成功后,是否还须要判断其余Realm的结果?

认证策略就是根据应用程序的须要对这些问题做出决断。 
认证策略是一个无状态的组件,在认证过程当中会通过4次的调用: 

  • 在全部Realm被调用以前

  • 在调用Realm的getAuthenticationInfo 方法以前

  • 在调用Realm的getAuthenticationInfo 方法以后

  • 在全部Realm被调用以后

认证策略的另一项工做就是聚合全部Realm的结果信息封装至一个AuthenticationInfo实例中,并将此信息返回,以此做为Subject的身份信息。 
Shiro有3中认证策略的具体实现:

ModularRealmAuthenticator 内置的认证策略默认实现是AtLeastOneSuccessfulStrategy 方式,由于这种方式也是被普遍使用的一种认证策略。固然,你也能够经过配置文件定义你须要的策略,如: 

[main]
...
authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy
...

三、Realm的顺序 

由刚才提到的认证策略,能够看到Realm在ModularRealmAuthenticator 里面的顺序对认证是有影响的。 
ModularRealmAuthenticator 会读取配置在SecurityManager里的Realm。当执行认证时,它会遍历Realm集合,对全部支持提交的token的Realm调用getAuthenticationInfo 。 

所以,若是Realm的顺序对你使用的认证策略结果有影响,那么你应该在配置文件中明肯定义Realm的顺序,如:

blahRealm = com.company.blah.Realm
...
fooRealm = com.company.foo.Realm
...
barRealm = com.company.another.Realm

securityManager.realms = $fooRealm, $barRealm, $blahRealm
相关文章
相关标签/搜索