Shiro官方快速入门10min例子源码解析框架3-Authentication(身份认证)

在作完预备的初始化和session测试后,到了作为一个权鉴别框架的核心功能部分,确认你是谁--身份认证(Authentication)。通过提交给shiro身份信息来验证是否与储存的安全信息数据是否相符来判断用户身份的真实性本文涉及到token的构建,框架结构下认证行为的调用,realm中授权数据的获取、登录信息比较,login过程中对已有有subject、session的处理同样,本篇本文使用的...

Shiro官方快速入门10min例子源码解析框架3-Authentication(身份认证)

在作完预备的初始化和session测试后,到了作为一个权鉴别框架的核心功能部分,确认你是谁--身份认证(Authentication)。

通过提交给shiro身份信息来验证是否与储存的安全信息数据是否相符来判断用户身份的真实性

本文涉及到token的构建,框架结构下认证行为的调用,realm中授权数据的获取、登录信息比较,login过程中对已有有subject、session的处理

同样,本篇本文使用的是shiro 1.3.2版本,配合源码最佳~

官方例子代码流程如下

cahlwftt

if (!currentUser.isAuthenticated()) {UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");token.setRememberMe(true);try { currentUser.login(token);} catch (UnknownAccountException uae) { log.info("There is no user with username of "   token.getPrincipal());} catch (IncorrectCredentialsException ice) { log.info("Password for account "token.getPrincipal()" was incorrect!");} catch (LockedAccountException lae) { log.info("The account for username "token.getPrincipal()" is locked.  "  "Please contact your administrator to unlock it.");}// ... catch more exceptions here (maybe custom ones specific to your application?catch (AuthenticationException ae) { //unexpected condition?  error?}  }

3.1首先构造token,其中 UsernamePasswordToken 实现了HostAuthenticationToken和RememberMeAuthenticationToken接口,他们都继承自AuthenticationToken接口

HostAuthenticationToken接口指定了token的域,RememberMeAuthenticationToken接口指定了token是否实现RememberMe(认证跨session)

ps:shiro 认证状态区分Authenticated和Remembered,Authenticated指当前session(或流程)下已经过认证,Remembered指曾经获得认证,如果是web状态下RememberMe相关信息保存在cookie中

二者可以调用 subject.isAuthenticated() 及subject.isRemembered()区分

其中UsernamePasswordToken 的Principal(身份)概念即Username,Credentials(凭证)概念即Password

enf5zggw

在token 中设置用户名和密码

UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");

设置是否使用RememberMe(此案例中不具体起作用,只是作为示例在token中设置

token.setRememberMe(true);

案例中不对host进行设置

3.2完成对token的构建设置后,便进行认证(Authentication)操作

currentUser.login(token);

首先先借用官方的例图来了解一下整个的流程

1-调用subject的login入口传入token

2-subject实际调用SecurityManager的login

3-securityManager再调用authenticator实例的doAuthenticate方法,一般这个是ModularRealmAuthenticator的实例

4-判断realm的状况,如果是单realm则直接调用realm,如果是多realm则要判断认证策略(AuthenticationStrategy)

5-调用对应realm中的getAuthenticationInfo实现进行认证

DelegatingSubject.login代码如下,下面对认证流程进行详细的解读

public void login(AuthenticationToken token) throws AuthenticationException {  clearRunAsIdentitiesInternal();  Subject subject = securityManager.login(this, token);  PrincipalCollection principals;  String host = null;  if (subject instanceof DelegatingSubject) {DelegatingSubject delegating = (DelegatingSubject) subject;//we have to do this in case there are assumed identities - we don't want to lose the 'real' principals:principals = delegating.principals;host = delegating.host;  } else {principals = subject.getPrincipals();  }  if (principals == null || principals.isEmpty()) {String msg = "Principals returned from securityManager.login( token ) returned a null or "    "empty value.  This value must be non null and populated with one or more elements.";throw new IllegalStateException(msg);  }  this.principals = principals;  this.authenticated = true;  if (token instanceof HostAuthenticationToken) {host = ((HostAuthenticationToken) token).getHost();  }  if (host != null) {this.host = host;  }  Session session = subject.getSession(false);  if (session != null) {this.session = decorate(session);  } else {this.session = null;  } }

3.2.1首先是初始化

clearRunAsIdentitiesInternal();

如果subject已含session则获取session并清除其中参数

3.2.2调用securityManager中的()login()开始认证

Subject subject = securityManager.login(this, token);

这里调用的是DefaultSecurityManager中的login

public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException {  AuthenticationInfo info;  try {info = authenticate(token);//调用AbstractAuthenticator.authenticate,  } catch (AuthenticationException ae) {try { onFailedLogin(token, ae, subject);//认证失败,清除remenberMe的信息使之失效} catch (Exception e) { if (log.isInfoEnabled()) {  log.info("onFailedLogin method threw an "   "exception.  Logging and propagating original AuthenticationException.", e); }}throw ae; //propagate  }  Subject loggedIn = createSubject(token, info, subject);  onSuccessfulLogin(token, info, loggedIn);  return loggedIn; }

3.2.2.1

调用AbstractAuthenticator.authenticate(),其中调用ModularRealmAuthenticator.doAuthenticate

protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {  assertRealmsConfigured();  Collection<Realm> realms = getRealms();  if (realms.size() == 1) {return doSingleRealmAuthentication(realms.iterator().next(), authentication
源文地址:https://www.guoxiongfei.cn/cntech/9875.html