首页 > 学院 > 开发设计 > 正文

Shiro-学习总结-认证

2019-11-08 01:35:58
字体:
来源:转载
供稿:网友

网上找到一张认证的相关图,如下

shiro第一个例子,参考quickstart的例子,相关文档可以去shiro官网下载

首先创建一个maven的工程,pom.xml文件内容如下:

	<dependency>	    <groupId>junit</groupId>	    <artifactId>junit</artifactId>	    <version>4.11</version>	</dependency>    <dependency>           <groupId>org.apache.shiro</groupId>           <artifactId>shiro-core</artifactId>           <version>1.2.2</version>       </dependency>        <dependency>	    <groupId>log4j</groupId>	    <artifactId>log4j</artifactId>	    <version>1.2.17</version>	</dependency>	<dependency>	    <groupId>org.slf4j</groupId>	    <artifactId>slf4j-log4j12</artifactId>	    <version>1.7.12</version>	</dependency>		<dependency>           <groupId>javax.servlet</groupId>           <artifactId>javax.servlet-api</artifactId>           <version>3.0.1</version>           <scope>PRovided</scope>       </dependency>       <dependency>           <groupId>javax.servlet</groupId>           <artifactId>jstl</artifactId>           <version>1.2</version>       </dependency>	<dependency>	    <groupId>javax.servlet.jsp</groupId>	    <artifactId>javax.servlet.jsp-api</artifactId>	    <version>2.3.1</version>	</dependency>          </dependencies>    <build>  	   <finalName>shiro</finalName>	   <plugins>	   	<plugin>	               <groupId>org.apache.tomcat.maven</groupId>	               <artifactId>tomcat7-maven-plugin</artifactId>	               <version>2.2</version>	               <configuration>	                   <path>/${project.build.finalName}</path>	               </configuration>	           </plugin>	   </plugins>  </build>java代码程序:

public class Quickstart {    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);    public static void main(String[] args) {    	  //构造SecurityManager		  Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");		  SecurityManager securityManager = factory.getInstance();				 		  SecurityUtils.setSecurityManager(securityManager);		 //获取当前subject		  Subject currentUser = SecurityUtils.getSubject();		 //获取session		  Session session = currentUser.getSession();		  session.setAttribute("someKey", "aValue");		  String value = (String) session.getAttribute("someKey");		  if (value.equals("aValue")) {		      log.info("Retrieved the correct value! [" + value + "]");		  }		 //测试当前用户是否已经登录即执行认证		  if (!currentUser.isAuthenticated()) {			  //用户名、密码封装为UsernamePassWordToken		      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 (AuthenticationException ae) {		      }		  }	 		  log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");		  		  //判断是否有某个角色  		  if (currentUser.hasRole("schwartz")) {		      log.info("May the Schwartz be with you!");		  } else {		      log.info("Hello, mere mortal.");		  }		 //判断是否有某个权限	  		  if (currentUser.isPermitted("lightsaber:wield")) {		      log.info("You may use a lightsaber ring.  Use it wisely.");		  } else {		      log.info("Sorry, lightsaber rings are for schwartz masters only.");		  }				  if (currentUser.isPermitted("winnebago:drive:eagle5")) {		      log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +		              "Here are the keys - have fun!");		  } else {		      log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");		      }			 //退出登录      		      currentUser.logout();		      System.exit(0);		  }}总结:

1、创建默认的securityManager,会默认注入iniRealm即表示从配置文件中获取用户相关信息。源码为:

    protected Realm createRealm(Ini ini) {        //IniRealm realm = new IniRealm(ini); changed to support SHIRO-322        IniRealm realm = new IniRealm();//默认为inirealm        realm.setName(INI_REALM_NAME);        realm.setIni(ini); //added for SHIRO-322        return realm;    }

2、用户通过currentUser.login(token)方法进行认证,内部调用securityManager.login(this, token),securityManager则是通过调用Authenticator的  public AuthenticationInfoauthenticate(AuthenticationToken authenticationToken)  throws AuthenticationException;方法进行认证。而Authenticator是一个接口,其接口实现类有如下图所示:

认证程序最终会去调用ModularRealmAuthenticator里的doAuthenticate(AuthenticationToken authenticationToken)方法【authenticationToken为用户输入的用户名,密码】。doAuthenticate方法源码如下:

    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {        assertRealmsConfigured();        Collection<Realm> realms = getRealms();        if (realms.size() == 1) {            return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);//单个realm        } else {            return doMultiRealmAuthentication(realms, authenticationToken);//多个realm        }    }

之后在根据realm个数,进行不同方法的调用:

//单个realm   
 protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) {        if (!realm.supports(token)) {            String msg = "Realm [" + realm + "] does not support authentication token [" +                    token + "].  Please ensure that the appropriate Realm implementation is " +                    "configured correctly or that the realm accepts AuthenticationTokens of this type.";            throw new UnsupportedTokenException(msg);        }        AuthenticationInfo info = realm.getAuthenticationInfo(token);        if (info == null) {            String msg = "Realm [" + realm + "] was unable to find account data for the " +                    "submitted AuthenticationToken [" + token + "].";            throw new UnknownAccountException(msg);        }        return info;    }

//多个realm
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {        AuthenticationStrategy strategy = getAuthenticationStrategy();        AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);        if (log.isTraceEnabled()) {            log.trace("Iterating through {} realms for PAM authentication", realms.size());        }        for (Realm realm : realms) {            aggregate = strategy.beforeAttempt(realm, token, aggregate);            if (realm.supports(token)) {                log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);                AuthenticationInfo info = null;                Throwable t = null;                try {                    info = realm.getAuthenticationInfo(token);                } catch (Throwable throwable) {                    t = throwable;                    if (log.isDebugEnabled()) {                        String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:";                        log.debug(msg, t);                    }                }                aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);            } else {                log.debug("Realm [{}] does not support token {}.  Skipping realm.", realm, token);            }        }        aggregate = strategy.afterAllAttempts(token, aggregate);        return aggregate;    }无论单个还是多个realm都会调用realm.getAuthenticationInfo(token),此时的realm默认为org.apache.shiro.realm.SimpleAccountRealm。代码如下:

    public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {        AuthenticationInfo info = getCachedAuthenticationInfo(token);        if (info == null) {            //otherwise not cached, perform the lookup:            info = doGetAuthenticationInfo(token);            log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);            if (token != null && info != null) {                cacheAuthenticationInfoIfPossible(token, info);            }        } else {            log.debug("Using cached authentication info [{}] to perform credentials matching.", info);        }        if (info != null) {            assertCredentialsMatch(token, info);//默认认证方法为SimpleCredentialsMatcher        } else {            log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}].  Returning null.", token);        }        return info;    }


上一篇:蓝牙 履带小车 制作

下一篇:数学知识

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表