您的位置:首页 > 其它

Shiro笔记(四)----身份验证之Realm

2017-07-15 15:58 344 查看
一、Realm简介

1.什么是Realm

Realm 是可以访问程序特定的安全数据如用户、角色、权限等的一个组件。Realm会将这些程序特定的安全数据转换成一种shiro可以理解的形式,shiro就可以依次提供容易理解的Subject程序API而不管有多少数据源或者程序中你的数据如何组织。

Realm 通常和数据源如数据库、LDAP目录、文件系统或者其它类似的数据源是一对一的关系,所以,可以用数据源相应的API如JDBC、File IO、 hibernate 或者JPA以及其它的API来实现Realm接口,从而获取授权的相关数据(角色、权限等)。

realm本质上就是一个指定安全的DAO。

因为大部分这类数据源通常都会同时存储认证数据(如密码)和授权数据(如角色和权限),所以每一个Shiro Realm都可以同时执行认证和授权操作。

总结: shiro要进行身份验证,就要从realm中获取相应的身份信息来进行验证,简单来说,我们可以自行定义realm,在realm中,从数据库获取身份信息,然后和 用户输入的身份信息进行匹配。这一切都由我们自己来定义。

2.为什么要用Realm

在前面的例子中,我们将身份信息(用户名/密码/角色/权限)写在配置文件中,但是实际开发中,这些身份信息应该保存在数据中,因此我们需要自定义Realm来从数据中获取身份信息,进行验证。

3.Realm 配置

如果使用Shiro的INI配置文件,你能够自定义及引用Realm,就像在[main]项中的任何其他对象一样,但它们在securityManager中采用两种方法之一进行配置:显式或隐式。

显式赋值:

这是一个显式的配置方法,在定义一个或多个Realm后,将它们作为securityManager对象的集合属性。

例如:

fooRealm = com.turing.foo.Realm

barRealm = com.turing.another.Realm

bazRealm = com.turing.baz.Realm

securityManager.realms = $fooRealm, $barRealm,$bazRealm

显式分配是确定的--你控制具体使用哪一个Realm及它们用于身份验证和授权的顺序,显示指定就是常见的方式,即定义Realm后再为securityManager按需要的顺序指定Realm。

隐式赋值:

如果因为某些原因(可能是定义的Realm太多?)不想为securityManager.realms指定,我们也可以使用隐式方式。

也就是说,把上面的配置改成如下形式就是隐式方式了:

fooRealm = com.company.foo.Realm

barRealm = com.company.another.Realm

bazRealm = com.company.baz.Realm


隐式方式其实就是不指定,只定义(define),Shiro会搜索配置中所有的Realm并将它们一一指定给securityManager。

使用隐式方式时只要稍微改一下Realm的定义,Shiro就可能会给我们来个惊喜。

4.Realms的认证实现

Shiro的认证过程最终会交由Realm执行,这时会调用Realm的getAuthenticationInfo(token)方法。

  

  该方法通常会在org.apache.shiro.realm.AuthenticatingRealm中实现,当然,这个方法中会调用到具体realm实现的方法。

该方法主要执行以下操作:

1、检查提交的进行认证的令牌信息

2、根据令牌信息从数据源(通常为数据库)中获取用户信息

3、对用户信息进行匹配验证。

4、验证通过将返回一个封装了用户信息的AuthenticationInfo实例。

5、验证失败则抛出AuthenticationException异常信息。

 

这是对所有Realm getAuthenticationInfo 实现的最高级别的工作流,验证通过后,就返回一个非空的AuthenticationInfo 实例来代表来自于该数据源的Subject 帐户信息。

5.身份验证流程

               身份验证: 即在应用中谁能证明他就是他本人。一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明。

5.1、基本概念

    Principals(身份):Subject 的 identifying attributes(标识属性)。比如我们登录提交的用户名。

    Credentials(凭证):用来作为一种起支持作用的证据,此证据包含身份证明。比如我们登录提供的密码。

5.2、认证的基本步骤

    收集Subjects 提交的Principals(身份)和Credentials(凭证);

    提交Principals(身份)和Credentials(凭证)进行身份验证;

    如果提交成功,则允许访问,否则重新进行身份验证或者阻止访问。

  AuthenticationToken:Shiro 中代表提交的 Principals(身份) 和 Credentials (凭证) 的身份验证系统的最基本接口。

  UsernamePasswordToken :AuthenticationToken 的接口的实现类,支持最常见的用户名/密码的身份验证

提交用户名/密码进行认证

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

5.3、处理认证成功和失败

    认证成功:没有返回,也没有异常,通过。

    认证失败,拋出异常,可以在程序中捕获并处理

5.4、认证顺序



5.5、认证过程



Step 1:应用程序代码调用 Subject.login 方法,传递创建好的包含终端用户的 Principals(身份)和 Credentials(凭证)的 AuthenticationToken 实例

Step 2:Subject 实例,通常为 DelegatingSubject(或子类)委托应用程序的 SecurityManager 通过调用 securityManager.login(token) 开始真正的验证。

Step 3:SubjectManager 接收 token,调用内部的 Authenticator 实例调用 authenticator.authenticate(token)。 Authenticator 通常是一个 ModularRealmAuthenticator 实例,支持在身份验证中协调一个或多个Realm 实例。

Step 4:如果应用程序中配置了一个以上的 Realm,ModularRealmAuthenticator 实例将利用配置好的AuthenticationStrategy 来启动 Multi-Realm 认证尝试。在Realms 被身份验证调用之前,期间和以后,AuthenticationStrategy 被调用使其能够对每个Realm 的结果作出反应。

Step 5:每个配置的 Realm 用来帮助看它是否支持提交的AuthenticationToken。如果支持,那么支持 Realm 的 getAuthenticationInfo 方法将会伴随着提交的 token 被调用。getAuthenticationInfo 方法有效地代表一

个特定 Realm 的单一的身份验证尝试。

二、使用Realm

首先自定义一个MyRealm类,继承AuthorizingRealm,父类AuthorizingRealm将获取Subject相关信息分成两步:获取身份验证信息(doGetAuthenticationInfo)及授权信息(doGetAuthorizationInfo);

1、doGetAuthenticationInfo 获取身份验证相关信息:首先根据传入的用户名获取User信息;然后如果user为空,那么抛出没找到帐号异常UnknownAccountException;如果user找到但锁定了抛出锁定异常LockedAccountException;最后生成AuthenticationInfo信息,交给间接父类AuthenticatingRealm使用CredentialsMatcher进行判断密码是否匹配,如果不匹配将抛出密码错误异常IncorrectCredentialsException;另外如果密码重试此处太多将抛出超出重试次数异常ExcessiveAttemptsException;

2、doGetAuthorizationInfo 获取授权信息:PrincipalCollection是一个身份集合,因为我们现在就一个Realm,所以直接调用getPrimaryPrincipal得到之前传入的用户名即可;然后根据用户名调用UserService接口获取角色及权限信息。

2.1、支持单个Realm

自定义一个Realm继承AuthorizingRealm实现其中的doGetAuthenticationInfo和doGetAuthorizationInfo方法:

package com.fendo.temp;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyRealm1 extends AuthorizingRealm {

private static final transient Logger log = LoggerFactory.getLogger(MyRealm1.class);

/**
* 获取身份信息,我们可以在这个方法中,从数据库获取该用户的权限和角色信息
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
log.info("----------doGetAuthorizationInfo方法被调用----------");
String username = (String) getAvailablePrincipal(principals);
//我们可以通过用户名从数据库获取权限/角色信息
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//权限
Set<String> s = new HashSet<String>();
s.add("printer:print");
s.add("printer:query");
info.setStringPermissions(s);
//角色
Set<String> r = new HashSet<String>();
r.add("role1");
info.setRoles(r);

return info;
}
/**
* 在这个方法中,进行身份验证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//用户名
String username = (String) token.getPrincipal();
log.info("username:"+username);
//密码
String password = new String((char[])token.getCredentials());
log.info("password:"+password);
//从数据库获取用户名密码进行匹配,这里为了方面,省略数据库操作
if(!"admin".equals(username)){
throw new UnknownAccountException();
}
if(!"123".equals(password)){
throw new IncorrectCredentialsException();
}
//身份验证通过,返回一个身份信息
AuthenticationInfo aInfo = new SimpleAuthenticationInfo(username,password,getName());

return aInfo;
}

}

然后新建一个测试类:

package com.fendo.temp;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {

private static final transient Logger log = LoggerFactory.getLogger(Main.class);

public static void main(String[] args) {

//获取SecurityManager的实例
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");

SecurityManager securityManager = factory.getInstance();

SecurityUtils.setSecurityManager(securityManager);

Subject currenUser = SecurityUtils.getSubject();

//如果还未认证
if(!currenUser.isAuthenticated()){
UsernamePasswordToken token = new UsernamePasswordToken("admin","123");
token.setRememberMe(true);
try {
currenUser.login(token);
} catch (UnknownAccountException uae) {
log.info("没有该用户: " + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
log.info( token.getPrincipal() + " 的密码不正确!");
} catch (LockedAccountException lae) {
log.info( token.getPrincipal() + " 被锁定 ,请联系管理员");
}catch (AuthenticationException ae) {
//其他未知的异常
}
}

if(currenUser.isAuthenticated())
log.info("用户 "+currenUser.getPrincipal() +" 登录成功");

//是否有role1这个角色
if(currenUser.hasRole("role1")){
log.info("有角色role1");
}else{
log.info("没有角色role1");
}
//是否有对打印机进行打印操作的权限
if(currenUser.isPermitted("printer:print")){
log.info("可以对打印机进行打印操作");
}else {
log.info("不可以对打印机进行打印操作");
}
}

}

在配置文件中配置(shiro-realm.ini)

#声明一个realm
MyRealm1=com.fendo.temp.MyRealm1
#指定securityManager的realms实现
securityManager.realms=$MyRealm1

doGetAuthorizationInfo会执行两次,分别是在currenUser.hasRole() 和currenUser.isPermitted 方法调用时调用 。

2.2、支持多个Realm

有时候不单单只有一个Realm而是由多个,Shiro支持多个Realm验证,新建一个MyRealm2

package com.fendo.temp;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyRealm2 extends AuthorizingRealm{

private static final transient Logger log = LoggerFactory.getLogger(Main.class);

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

String username = (String) getAvailablePrincipal(principals);
//通过用户名从数据库获取权限字符串
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//权限
Set<String> s = new HashSet<String>();
s.add("printer:print");
s.add("printer:query");
info.setStringPermissions(s);
//角色
Set<String> r = new HashSet<String>();
r.add("role1");
info.setRoles(r);

return info;
}

@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
log.info("MyRealm2开始认证。。。。。。");
//用户名
String username = (String) token.getPrincipal();
log.info("username:"+username);
//密码
String password = new String((char[])token.getCredentials());
log.info("password:"+password);
//从数据库获取用户名密码进行匹配,这里为了方面,省略数据库操作
if(!"admin".equals(username)){
throw new UnknownAccountException();
}
if(!"123".equals(password)){
throw new IncorrectCredentialsException();
}
//身份验证通过
AuthenticationInfo aInfo = new SimpleAuthenticationInfo(username,password,getName());

return aInfo;
}

}


然后在ini文件中进行配置,Realm验证的顺序就是在ini文件中配置的顺序,如下:

#声明一个realm  
MyRealm1=com.fendo.temp.MyRealm1
MyRealm2=com.fendo.temp.MyRealm2
#ָ配置验证器
securityManager.realms=$MyRealm1
#配置验证器
authenticator = org.apache.shiro.authc.pam.ModularRealmAuthenticator
#配置策略
# AllSuccessfulStrategy 表示 MyRealm1和MyRealm2 认证都通过才算通过
authcStrategy = org.apache.shiro.authc.pam.AllSuccessfulStrategy
#将验证器和策略关联起来
authenticator.authenticationStrategy = $authcStrategy
#配置验证器所使用的Realm
authenticator.realms=$MyRealm2,$MyRealm1

#把Authenticator设置给securityManager
securityManager.authenticator = $authenticator

##########################################################################
# 1. AtLeastOneSuccessfulStrategy :如果一个(或更多)Realm 验证成功,则整体的尝试被认
# 为是成功的。如果没有一个验证成功,则整体尝试失败。

# 2. FirstSuccessfulStrategy 只有第一个成功地验证的Realm 返回的信息将被使用。所有进一步
# 的Realm 将被忽略。如果没有一个验证成功,则整体尝试失败

# 3. AllSucessfulStrategy 为了整体的尝试成功,所有配置的Realm 必须验证成功。如果没有一
# 个验证成功,则整体尝试失败。

# ModularRealmAuthenticator 默认的是AtLeastOneSuccessfulStrategy
###########################################################################

securityManager会按照realms指定的顺序进行身份认证,其中有两个地方要注意下就是,Authenticator和AuthenticationStrategy,Strategy的意思就是策略。Authenticator就是验证器。

Authenticator的职责是验证用户帐号,是Shiro API中身份验证核心的入口点: 

public AuthenticationInfo authenticate(AuthenticationToken authenticationToken)  throws AuthenticationException;

如果验证成功,将返回AuthenticationInfo验证信息;此信息中包含了身份及凭证;如果验证失败将抛出相应的AuthenticationException实现。

SecurityManager接口继承了Authenticator,另外还有一个ModularRealmAuthenticator实现,其委托给多个Realm进行验证,验证规则通过AuthenticationStrategy接口指定,默认提供的实现:

FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略;

AtLeastOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,返回所有Realm身份验证成功的认证信息;

AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。

 

ModularRealmAuthenticator默认使用AtLeastOneSuccessfulStrategy策略。

新建测试类mains:

package com.fendo.temp;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Mains {

private static final transient Logger log = LoggerFactory.getLogger(Main.class);

public static void main(String[] args) {
//获取SecurityManager的实例
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-mutil-realm.ini");
SecurityManager securityManager = factory.getInstance();

SecurityUtils.setSecurityManager(securityManager);

Subject currenUser = SecurityUtils.getSubject();

//如果还未认证
if(!currenUser.isAuthenticated()){
UsernamePasswordToken token = new UsernamePasswordToken("admin","123");
token.setRememberMe(true);
try {
currenUser.login(token);
} catch (UnknownAccountException uae) {
log.info("没有该用户: " + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
log.info( token.getPrincipal() + " 的密码不正确!");
} catch (LockedAccountException lae) {
log.info( token.getPrincipal() + " 被锁定 ,请联系管理员");
}catch (AuthenticationException ae) {
//其他未知的异常
}
}

if(currenUser.isAuthenticated())
log.info("用户 "+currenUser.getPrincipal() +" 登录成功");

//得到一个身份集合
PrincipalCollection principalCollection = currenUser.getPrincipals();

}
}

输出如下:

2017-07-15 15:31:53,809 INFO [com.fendo.temp.Main] - MyRealm2开始认证。。。。。。
2017-07-15 15:31:53,809 INFO [com.fendo.temp.Main] - username:admin
2017-07-15 15:31:53,809 INFO [com.fendo.temp.Main] - password:123

2017-07-15 15:31:53,814 INFO [com.fendo.temp.MyRealm1] - MyRealm1开始认证。。。。。。
2017-07-15 15:31:53,814 INFO [com.fendo.temp.MyRealm1] - username:admin
2017-07-15 15:31:53,814 INFO [com.fendo.temp.MyRealm1] - password:123

MyRealm1和MyRealm2依次执行。

2.3、自定义AuthenticationStrategy(验证策略)

我们也可以自定义AuthenticationStrategy,首先看其API:

//在所有Realm验证之前调用
AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException;

//在每个Realm之前调用
AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException;

//在每个Realm之后调用
AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException;

//在所有Realm之后调用
AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException;

新建一个类继承AbstractAuthenticationStrategy:

package com.fendo.temp;

import java.util.Collection;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.AbstractAuthenticationStrategy;
import org.apache.shiro.realm.Realm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyAuthenticationStrategy extends AbstractAuthenticationStrategy{

private static final transient Logger log = LoggerFactory.getLogger(MyAuthenticationStrategy.class);
/**
* 所有Realm验证之前调用
*/
@Override
public AuthenticationInfo beforeAllAttempts(
Collection<? extends Realm> realms, AuthenticationToken token)
throws AuthenticationException {
log.info("===============beforeAllAttempts方法被调用==================");
return super.beforeAllAttempts(realms, token);
}
/**
* 每一个Realm验证之前调用
*/
@Override
public AuthenticationInfo beforeAttempt(Realm realm,
AuthenticationToken token, AuthenticationInfo aggregate)
throws AuthenticationException {
log.info("===============beforeAttempt方法被调用==================");
return super.beforeAttempt(realm, token, aggregate);
}
/**
* 每一个Realm验证之后调用
*/
@Override
public AuthenticationInfo afterAttempt(Realm realm,
AuthenticationToken token, AuthenticationInfo singleRealmInfo,
AuthenticationInfo aggregateInfo, Throwable t)
throws AuthenticationException {
log.info("===============afterAttempt方法被调用==================");
return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t);
}
/**
* 所有Realm验证之后调用
*/
@Override
public AuthenticationInfo afterAllAttempts(AuthenticationToken token,
AuthenticationInfo aggregate) throws AuthenticationException {
log.info("===============afterAllAttempts方法被调用==================");
return super.afterAllAttempts(token, aggregate);
}
}


要想让我们自定义的AbstractAuthenticationStrategy起作用,需在ini配置文件中将authcStrategy =org.apache.shiro.authc.pam.AllSuccessfulStrategy 

改为authcStrategy = com.shiro.authenticationstrategy.MyAuthenticationStrategy 即可,测试代码不变,然后运行mains,查看运行结果如下:

2017-07-15 15:42:37,464 INFO [com.fendo.temp.MyAuthenticationStrategy] - ===============beforeAllAttempts方法被调用==================
2017-07-15 15:42:37,466 TRACE [org.apache.shiro.authc.pam.ModularRealmAuthenticator] - Iterating through 2 realms for PAM authentication
2017-07-15 15:42:37,466 INFO [com.fendo.temp.MyAuthenticationStrategy] - ===============beforeAttempt方法被调用==================
2017-07-15 15:42:37,466 TRACE [org.apache.shiro.authc.pam.ModularRealmAuthenticator] - Attempting to authenticate token [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=true] using realm [com.fendo.temp.MyRealm2@17d99928]
2017-07-15 15:42:37,466 INFO [com.fendo.temp.Main] - MyRealm2开始认证。。。。。。
2017-07-15 15:42:37,466 INFO [com.fendo.temp.Main] - username:admin
2017-07-15 15:42:37,466 INFO [com.fendo.temp.Main] - password:123
2017-07-15 15:42:37,469 DEBUG [org.apache.shiro.realm.AuthenticatingRealm] - Looked up AuthenticationInfo [admin] from doGetAuthenticationInfo
2017-07-15 15:42:37,469 DEBUG [org.apache.shiro.realm.AuthenticatingRealm] - AuthenticationInfo caching is disabled for info [admin].  Submitted token: [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=true].
2017-07-15 15:42:37,469 DEBUG [org.apache.shiro.authc.credential.SimpleCredentialsMatcher] - Performing credentials equality check for tokenCredentials of type [[C and accountCredentials of type [java.lang.String]
2017-07-15 15:42:37,469 DEBUG [org.apache.shiro.authc.credential.SimpleCredentialsMatcher] - Both credentials arguments can be easily converted to byte arrays.  Performing array equals comparison
2017-07-15 15:42:37,470 INFO [com.fendo.temp.MyAuthenticationStrategy] - ===============afterAttempt方法被调用==================
2017-07-15 15:42:37,470 INFO [com.fendo.temp.MyAuthenticationStrategy] - ===============beforeAttempt方法被调用==================
2017-07-15 15:42:37,471 TRACE [org.apache.shiro.authc.pam.ModularRealmAuthenticator] - Attempting to authenticate token [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=true] using realm [com.fendo.temp.MyRealm1@2fc14f68]
2017-07-15 15:42:37,471 INFO [com.fendo.temp.MyRealm1] - MyRealm1开始认证。。。。。。
2017-07-15 15:42:37,471 INFO [com.fendo.temp.MyRealm1] - username:admin
2017-07-15 15:42:37,471 INFO [com.fendo.temp.MyRealm1] - password:123
2017-07-15 15:42:37,471 DEBUG [org.apache.shiro.realm.AuthenticatingRealm] - Looked up AuthenticationInfo [admin] from doGetAuthenticationInfo
2017-07-15 15:42:37,471 DEBUG [org.apache.shiro.realm.AuthenticatingRealm] - AuthenticationInfo caching is disabled for info [admin].  Submitted token: [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=true].
2017-07-15 15:42:37,471 DEBUG [org.apache.shiro.authc.credential.SimpleCredentialsMatcher] - Performing credentials equality check for tokenCredentials of type [[C and accountCredentials of type [java.lang.String]
2017-07-15 15:42:37,471 DEBUG [org.apache.shiro.authc.credential.SimpleCredentialsMatcher] - Both credentials arguments can be easily converted to byte arrays.  Performing array equals comparison
2017-07-15 15:42:37,471 INFO [com.fendo.temp.MyAuthenticationStrategy] - ===============afterAttempt方法被调用==================
2017-07-15 15:42:37,472 INFO [com.fendo.temp.MyAuthenticationStrategy] - ===============afterAllAttempts方法被调用==================
2017-07-15 15:42:38,043 INFO [com.fendo.temp.Main] - 用户 admin 登录成功

可以从上面的输出中,清楚的看到我们自定义的策略中,各个方法被调用的顺序。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: