乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Shiro框架Web環(huán)境下過(guò)濾器結(jié)構(gòu)分析

       昵稱(chēng)11608230 2014-01-12

      這篇寫(xiě)得非常不錯(cuò),很細(xì)

      原文地址:http://blog.csdn.net/jacky_zuo/article/details/7000402

      Shiro的過(guò)濾器的配置是結(jié)合使用Spring的DelegatingFilterProxy與FactoryBean2種技術(shù)來(lái)完成自身過(guò)濾器的植入的,所以理解Shiro的過(guò)濾器首先要理解這2者的使用。


      1. DelegatingFilterProxy

      Spring提供的一個(gè)簡(jiǎn)便的過(guò)濾器的處理方案,它將具體的操作交給內(nèi)部的Filter對(duì)象delegate去處理,而這個(gè)delegate對(duì)象通過(guò)Spring IOC容器獲取,這里采用的是Spring的FactoryBean的方式獲取這個(gè)對(duì)象。

      DelegatingFilterProxy的配置如下

      1. <filter>   
      2.     <filter-name>shiroFilter</filter-name>  
      3.     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
      4.     <init-param>  
      5.          <param-name>targetFilterLifecycle</param-name>   
      6.          <param-value>true</param-value>   
      7.     </init-param>   
      8. </filter>  

      雖然只配置了這一個(gè)filter,但是它并做任何實(shí)際的工作,而是把工作交由Spring中容器為bean的名字shiroFilter的類(lèi),即ShiroFilterFactoryBean;


      2. ShiroFilterFactoryBean

      配置如下

      1. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
      2.     ..  
      3. </bean>  

      由于它是個(gè)FactroyBean,所以上面的delegate真正的對(duì)象是通過(guò)它的getObject()獲取的。

      這里是FactoryBean接口獲取實(shí)例的標(biāo)準(zhǔn)方法

      1. public Object getObject() throws Exception {  
      2.         if (instance == null) {  
      3.             instance = createInstance();  
      4.         }  
      5.         return instance;  
      6.     }  

      這里是真正創(chuàng)建對(duì)象的方法

      1. protected AbstractShiroFilter createInstance() throws Exception {  
      2.   
      3.         log.debug("Creating Shiro Filter instance.");  
      4.   
      5.         SecurityManager securityManager = getSecurityManager();  
      6.         if (securityManager == null) {  
      7.             String msg = "SecurityManager property must be set.";  
      8.             throw new BeanInitializationException(msg);  
      9.         }  
      10.   
      11.         if (!(securityManager instanceof WebSecurityManager)) {  
      12.             String msg = "The security manager does not implement the WebSecurityManager interface.";  
      13.             throw new BeanInitializationException(msg);  
      14.         }  
      15.   
      16.         FilterChainManager manager = createFilterChainManager();  
      17.   
      18.         //Expose the constructed FilterChainManager by first wrapping it in a  
      19.         // FilterChainResolver implementation. The AbstractShiroFilter implementations  
      20.         // do not know about FilterChainManagers - only resolvers:  
      21.         PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();  
      22.         chainResolver.setFilterChainManager(manager);  
      23.   
      24.         //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built  
      25.         //FilterChainResolver.  It doesn't matter that the instance is an anonymous inner class  
      26.         //here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts  
      27.         //injection of the SecurityManager and FilterChainResolver:  
      28.         return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);  
      29.     }  
      所以真正完成實(shí)際工作的過(guò)濾器是SpringShiroFilter,這個(gè)對(duì)象才是真正的delegate。


      3. SpringShiroFilter: ShiroFilterFactoryBean的內(nèi)部類(lèi),繼承AbstractShiroFilter

      1. private static final class SpringShiroFilter extends AbstractShiroFilter {  
      2.   
      3.         protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {  
      4.             super();  
      5.             if (webSecurityManager == null) {  
      6.                 throw new IllegalArgumentException("WebSecurityManager property cannot be null.");  
      7.             }  
      8.             setSecurityManager(webSecurityManager);  
      9.             if (resolver != null) {  
      10.                 setFilterChainResolver(resolver);  
      11.             }  
      12.         }  
      13.     }  

      4. OncePerRequestFilter : AbstractShiroFilter的父類(lèi)

      關(guān)鍵方法

      1. protected abstract void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)  
      2.             throws ServletException, IOException;  

      這個(gè)方法有過(guò)濾器中調(diào)用:

      1. public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)  
      2.             throws ServletException, IOException {  
      3.         String alreadyFilteredAttributeName = getAlreadyFilteredAttributeName();  
      4.         if (request.getAttribute(alreadyFilteredAttributeName) != null || shouldNotFilter(request)) {  
      5.             log.trace("Filter '{}' already executed.  Proceeding without invoking this filter.", getName());  
      6.             // Proceed without invoking this filter...  
      7.             filterChain.doFilter(request, response);  
      8.         } else {  
      9.             // Do invoke this filter...  
      10.             log.trace("Filter '{}' not yet executed.  Executing now.", getName());  
      11.             request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);  
      12.   
      13.             try {  
      14.                 doFilterInternal(request, response, filterChain);  
      15.             } finally {  
      16.                 // Once the request has finished, we're done and we don't  
      17.                 // need to mark as 'already filtered' any more.  
      18.                 request.removeAttribute(alreadyFilteredAttributeName);  
      19.             }  
      20.         }  
      21.     }  
      doFilterInternal這個(gè)方法有2處實(shí)現(xiàn),1是AbstractShiroFilter的實(shí)現(xiàn),2是AdviceFilter的實(shí)現(xiàn)。通過(guò)查看shiro的內(nèi)定義的Filter繼承結(jié)構(gòu)可以看出,除了SpringShiroFilter這個(gè)內(nèi)部類(lèi)是繼承前者,其他所有的用到的Filter都是繼承后者。SpringShiroFilter是每次請(qǐng)求的第一個(gè)真正處理實(shí)際工作的Filter(主要是創(chuàng)建一個(gè)Subject并綁定相關(guān)數(shù)據(jù))。

      5. AbstractShiroFilter:OncePerRequestFilter的第一個(gè)子類(lèi)

      1. protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)  
      2.             throws ServletException, IOException {  
      3.   
      4.         Throwable t = null;  
      5.   
      6.         try {  
      7.             final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);  
      8.             final ServletResponse response = prepareServletResponse(request, servletResponse, chain);  
      9.   
      10.             final Subject subject = createSubject(request, response);  
      11.   
      12.             //noinspection unchecked  
      13.             subject.execute(new Callable() {  
      14.                 public Object call() throws Exception {  
      15.                     updateSessionLastAccessTime(request, response);  
      16.                     executeChain(request, response, chain);  
      17.                     return null;  
      18.                 }  
      19.             });  
      20.         } catch (ExecutionException ex) {  
      21.             t = ex.getCause();  
      22.         } catch (Throwable throwable) {  
      23.             t = throwable;  
      24.         }  
      25.   
      26.         if (t != null) {  
      27.             if (t instanceof ServletException) {  
      28.                 throw (ServletException) t;  
      29.             }  
      30.             if (t instanceof IOException) {  
      31.                 throw (IOException) t;  
      32.             }  
      33.             //otherwise it's not one of the two exceptions expected by the filter method signature - wrap it in one:  
      34.             String msg = "Filtered request failed.";  
      35.             throw new ServletException(msg, t);  
      36.         }  
      37.     }  

      這段代碼表示每次經(jīng)過(guò)AbstractShiroFilter的doFilterInternal方法(具體的類(lèi)也就是上面的內(nèi)部類(lèi)SpringShiroFilter)都會(huì)創(chuàng)建一個(gè)新的Subject,具體分析里面的代碼可以發(fā)現(xiàn),這個(gè)Subject的數(shù)據(jù)會(huì)從SubjectContext或Session中獲取過(guò)來(lái)。這意味著每次經(jīng)過(guò)Shiro過(guò)濾器的HTTP請(qǐng)求,都會(huì)創(chuàng)建一次新的Subject.

      Suject里面的數(shù)據(jù),主要是從SubjectContext中獲取,但是獲取方式不一樣,如SecurityManager總是從SubjectContext中直接獲取,而其他數(shù)據(jù)則主要從Session中獲取。只有在登錄操作的時(shí)候數(shù)據(jù)會(huì)都從SubjectContext上下文中獲取。因?yàn)榈卿洺晒筮€會(huì)有一個(gè)綁定操作,它會(huì)把當(dāng)前用戶(hù)的相關(guān)信息寫(xiě)入Session中去。

      DefaultSecurityManager代碼如下:

      1. protected void bind(Subject subject) {  
      2.         // TODO consider refactoring to use Subject.Binder.  
      3.         // This implementation was copied from SessionSubjectBinder that was removed  
      4.         PrincipalCollection principals = subject.getPrincipals();  
      5.         if (principals != null && !principals.isEmpty()) {  
      6.             Session session = subject.getSession();  
      7.             bindPrincipalsToSession(principals, session);  
      8.         } else {  
      9.             Session session = subject.getSession(false);  
      10.             if (session != null) {  
      11.                 session.removeAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);  
      12.             }  
      13.         }  
      14.   
      15.         if (subject.isAuthenticated()) {  
      16.             Session session = subject.getSession();  
      17.             session.setAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY, subject.isAuthenticated());  
      18.         } else {  
      19.             Session session = subject.getSession(false);  
      20.             if (session != null) {  
      21.                 session.removeAttribute(DefaultSubjectContext.AUTHENTICATED_SESSION_KEY);  
      22.             }  
      23.         }  
      24.     }  

      1. private void bindPrincipalsToSession(PrincipalCollection principals, Session session) throws IllegalArgumentException {  
      2.         if (session == null) {  
      3.             throw new IllegalArgumentException("Session argument cannot be null.");  
      4.         }  
      5.         if (CollectionUtils.isEmpty(principals)) {  
      6.             throw new IllegalArgumentException("Principals cannot be null or empty.");  
      7.         }  
      8.         session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, principals);  
      9.     }  

      其他登錄相關(guān)的信息綁定到SubjectContext的操作代碼如下,每個(gè)set方法的調(diào)用都將數(shù)據(jù)保存到SubjectContext:

      1. protected Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing) {  
      2.         SubjectContext context = createSubjectContext();  
      3.         context.setAuthenticated(true);  
      4.         context.setAuthenticationToken(token);  
      5.         context.setAuthenticationInfo(info);  
      6.         if (existing != null) {  
      7.             context.setSubject(existing);  
      8.         }  
      9.         return createSubject(context);  
      10.     }  


      6. AdviceFilter:OncePerRequestFilter的第二個(gè)子類(lèi) 

      它是全部的驗(yàn)證與授權(quán)Filter的父類(lèi),其doFilterInternal方法承擔(dān)此類(lèi)過(guò)濾器的核心邏輯。

      1. public void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)  
      2.             throws ServletException, IOException {  
      3.   
      4.         Exception exception = null;  
      5.   
      6.         try {  
      7.   
      8.             boolean continueChain = preHandle(request, response);  
      9.             if (log.isTraceEnabled()) {  
      10.                 log.trace("Invoked preHandle method.  Continuing chain?: [" + continueChain + "]");  
      11.             }  
      12.   
      13.             if (continueChain) {  
      14.                 executeChain(request, response, chain);  
      15.             }  
      16.   
      17.             postHandle(request, response);  
      18.             if (log.isTraceEnabled()) {  
      19.                 log.trace("Successfully invoked postHandle method");  
      20.             }  
      21.   
      22.         } catch (Exception e) {  
      23.             exception = e;  
      24.         } finally {  
      25.             cleanup(request, response, exception);  
      26.         }  
      27.     }  
      從上面的代碼可以看出,其核心的邏輯是3個(gè)部分: preHandle, executeChain,postHandle。后2者都只有該類(lèi)中有唯一的實(shí)現(xiàn),子類(lèi)并不覆蓋,而preHandle則由一個(gè)子類(lèi)PathMatchingFilter中覆蓋,代碼如下:

      1. public boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {  
      2.   
      3.         if (this.appliedPaths == null || this.appliedPaths.isEmpty()) {  
      4.             if (log.isTraceEnabled()) {  
      5.                 log.trace("appliedPaths property is null or empty.  This Filter will passthrough immediately.");  
      6.             }  
      7.             return true;  
      8.         }  
      9.   
      10.         for (String path : this.appliedPaths.keySet()) {  
      11.             // If the path does match, then pass on to the subclass implementation for specific checks  
      12.             //(first match 'wins'):  
      13.             if (pathsMatch(path, request)) {  
      14.                 if (log.isTraceEnabled()) {  
      15.                     log.trace("Current requestURI matches pattern [" + path + "].  Performing onPreHandle check...");  
      16.                 }  
      17.                 Object config = this.appliedPaths.get(path);  
      18.                 return onPreHandle(request, response, config);  
      19.             }  
      20.         }  
      21.   
      22.         //no path matched, allow the request to go through:  
      23.         return true;  
      24.     }  

      這個(gè)方法根據(jù)用戶(hù)請(qǐng)求的地址是否與該Filter配置的地址匹配來(lái)決定是否調(diào)用內(nèi)部的onPreHandler方法。從shiroFilter中的屬性filterChainDefinitions配置中可以看出,shiro默認(rèn)的那些過(guò)濾器如user,roles,perms等等都可以統(tǒng)一使用這種方式,對(duì)于內(nèi)部的處理則分別由各個(gè)Filter的onPreHandler(其實(shí)是由內(nèi)部的isAccessAllowed和onAccessDenied方法)來(lái)決定了。

      舉2個(gè)例子

      第一個(gè)是AuthenticationFilter的isAccessAllowed方法,它只檢測(cè)用戶(hù)是否通過(guò)驗(yàn)證

      1. protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {  
      2.         Subject subject = getSubject(request, response);  
      3.         return subject.isAuthenticated();  
      4.     }  
      第二個(gè)是RolesAuthorizationFilter的isAccessAllowed方法,它檢測(cè)用戶(hù)的角色是否滿(mǎn)足
      1. public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {  
      2.   
      3.        Subject subject = getSubject(request, response);  
      4.        String[] rolesArray = (String[]) mappedValue;  
      5.   
      6.        if (rolesArray == null || rolesArray.length == 0) {  
      7.            //no roles specified, so nothing to check - allow access.  
      8.            return true;  
      9.        }  
      10.   
      11.        Set<String> roles = CollectionUtils.asSet(rolesArray);  
      12.        return subject.hasAllRoles(roles);  
      13.    } 

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多