shiro认证源码

一、web.xml中配置:html

  1. <filter>  
  2.     <filter-name>shiroFilter</filter-name>  
  3.     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  4.     <async-supported>true</async-supported>  
  5.     <init-param>  
  6.         <param-name>targetFilterLifecycle</param-name>  
  7.         <param-value>true</param-value>  
  8.     </init-param>  
  9. </filter>  
  10. <filter-mapping>  
  11.     <filter-name>shiroFilter</filter-name>  
  12.     <url-pattern>/*</url-pattern>  
  13. </filter-mapping> 
             这只是一个代理,执行流程委托给Spring容器中名为shiroFilter(上面同名的filter-name)的过滤器


二、shiro-spring.xml:web

  1. <!-- Shiro的Web过滤器 -->  
  2. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  3.     <property name="securityManager" ref="securityManager"/>  
  4.     <property name="loginUrl" value="/login.jsp"/>  
  5.     <property name="unauthorizedUrl" value="/unauthorized.jsp"/>  
  6.     <property name="filters">  
  7.         <util:map>  
  8.             <entry key="authc" value-ref="formAuthenticationFilter"/>  
  9.         </util:map>  
  10.     </property>  
  11.     <property name="filterChainDefinitions">  
  12.         <value>  
  13.             /index.jsp = anon  
  14.             /unauthorized.jsp = anon  
  15.             /login.jsp = authc  
  16.             /logout = logout  
  17.             /authenticated.jsp = authc   
  18.             /** = user  
  19.         </value>  
  20.     </property>  
  21. </bean> 
                ShiroFilterFactoryBean实现了org.springframework.beans.factory.FactoryBean接口,因此由ShiroFilterFactoryBean的getObject()方法返回一个           

                  SpringShiroFilter对  象,即Spring配置文件中的shiroFilter对象,该过滤器拥有三个重要对象:spring

                                  SecurityManager、apache

                                  PathMatchingFilterChainResolver、                               缓存

                                  FilterChainManagerapp

                  当匹配到过滤链中的aauthc对应的url时,会执行匹配对应<entry key="authc" value-ref="formAuthenticationFilter"/>,既然是filter,那么最jsp

                  重要的就是doFilter方法了,通过执行父类的一系列方法后最终执行到FormAuthenticationFilter类中的onAccessDenied方法async

   

  1. protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {  
  2.     // 第一次访问天然不是登陆请求  
  3.     if (isLoginRequest(request, response)) {  
  4.         // 判断是不是POST请求  
  5.         if (isLoginSubmission(request, response)) {  
  6.             if (log.isTraceEnabled()) {  
  7.                 log.trace("Login submission detected.  Attempting to execute login.");  
  8.             }  
  9.             return executeLogin(request, response);  

                  

                  接着执行父类AuthenticatingFilter中的executeLogin()方法,建立token的方法createToken()能够重写放回自定义实现UsernamePasswordToken的this

                  类MyUsernamePasswordToken(能够实现实际的业务逻辑)url

  1. protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {  
  2.     // 根据表单填写的用户名密码建立AuthenticationToken  
  3.     AuthenticationToken token = createToken(request, response);  
  4.     if (token == null) {  
  5.         String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " +  
  6.                 "must be created in order to execute a login attempt.";  
  7.         throw new IllegalStateException(msg);  
  8.     }  
  9.     try {  
  10.         // 获取Subject对象  
  11.         Subject subject = getSubject(request, response);  
  12.         // 执行Subject.login方法进行登陆  
  13.         subject.login(token);  
  14.         // 若是登陆成功,重定向至上次访问的URL  
  15.         return onLoginSuccess(token, subject, request, response);  
               

                 接着执行subject的实现类DelegatingSubject中的login()方法

                   

                 接着执行securityManager实现类DefaultSecurityManager的login()方法

                 

                 接着执行AuthenticatingSecurityManager中的authenticate( )方法,该方法this.authenticator返回的是ModularRealmAuthenticator

                 

                 执行ModularRealmAuthenticator中的authenticaticate( )方法,由于其继承AbstractAuthenticator,因此执行AbstractAuthenticator中的authenticaticate( )

                   

                 接着执行ModularRealmAuthenticator中的doAuthenticate( )方法

                        

                 其中realm.getAuthenticationInfo( ),realm为Realm接口,实际上调用的是其实现类AuthenticatingRealm中的getAuthenticationInfo( )方法

                 

                上述代码AuthenticationInfo info = getCachedAuthenticationInfo(token);从缓存中获取认证信息,若是未获取到,则调用doGetAuthenticationInfo(token)

                方法获取认证信息,获取到认证信息info后执行assertCredentialsMatch( )方法

                     

                 getCredentialsMatcher( )返回咱们自定义实现SimpleCredentialsMatcher的类MyCredentialsMatcher,接着cm.doCredentialMatch( )调用实现类方法

                        

                校验成功后则执行下面的跳转方法onLoginSuccess( )

                           

                接着执行实现FormAuthenticationFilter的方法

                         

                        认证成功执行FormAuthenticationFilter中的onLoginSuccess()方法,调用issueSuccessRedirect( ),

                        接着执行AuthenticationFilter中的issueSuccessRedirect( )

                        

                        认证失败则执行FormAuthenticationFilter中的onLoginFailure方法,接着执行FormAuthenticationFilter中的setFailureAttribute( )方法

                        getFailureKeyAttribute( )方法返回的事一个final字符窜:DEFAULT_ERROR_KEY_ATTRIBUTE_NAME

                        

            接着在LoginController中获取到key对应的值进行异常抛出

                  


参考文献:http://www.cnblogs.com/ccfdod/p/6436353.html

                http://blog.csdn.net/xtayfjpk/article/details/53729135

                http://jinnianshilongnian.iteye.com/blog/2029717