Spring Security權限框架理論與實戰(二)-常用權限攔截器1 SecurityContextPersistenceFilter

1 SecurityContextPersistenceFilter

通過觀察Filter的名字,就能大概猜出來這個過濾器的作用,持久化SecurityContext實例 org.springframework.security.web.context.SecurityContextPersistenceFilter

該 Filter 位於過濾器的頂端,所有過濾器的入口

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (request.getAttribute(FILTER_APPLIED) != null) {
            // 確保對於每個請求只應用一次過濾器
            chain.doFilter(request, response);
            return;
        }

        final boolean debug = logger.isDebugEnabled();

        request.setAttribute(FILTER_APPLIED, Boolean.TRUE);

        if (forceEagerSessionCreation) {
            HttpSession session = request.getSession();

            if (debug && session.isNew()) {
                logger.debug("Eagerly created session: " + session.getId());
            }
        }
        // 將 request/response 對象交給該對象維護  
        HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request,response);
        //通過SecurityContextRepository接口的實現類裝載SecurityContext實例  
        //HttpSessionSecurityContextRepository將產生SecurityContext實例的任務交給SecurityContextHolder.createEmptyContext()  
        //SecurityContextHolder再根據策略模式的不同,  
        //把任務再交給相應策略類完成SecurityContext的創建  
        //如果沒有配置策略名稱,則默認爲  
        //ThreadLocalSecurityContextHolderStrategy,  
        //該類直接通過new SecurityContextImpl()創建實例
        SecurityContext contextBeforeChainExecution = repo.loadContext(holder);

        try {
            //將產生的SecurityContext再通過SecurityContextHolder->  
            //ThreadLocalSecurityContextHolderStrategy設置到ThreadLocal 
            SecurityContextHolder.setContext(contextBeforeChainExecution);
            //繼續把請求流向下一個過濾器執行  
            chain.doFilter(holder.getRequest(), holder.getResponse());

        }
        finally {
            // 所有過濾器執行完後

            //先從SecurityContextHolder獲取SecurityContext實例  
            SecurityContext contextAfterChainExecution = SecurityContextHolder
                    .getContext();
            //關鍵性地除去SecurityContextHolder內容 - 在任何事情之前執行此操作
            //再把SecurityContext實例從SecurityContextHolder中清空
                        //若沒有清空,會受到服務器的線程池機制的影響  
            SecurityContextHolder.clearContext();
            //將SecurityContext實例持久化到session中 
            repo.saveContext(contextAfterChainExecution, holder.getRequest(),
                    holder.getResponse());
            request.removeAttribute(FILTER_APPLIED);

            if (debug) {
                logger.debug("SecurityContextHolder now cleared, as request processing completed");
            }
        }
    }

該Filter的作用主要是創建一個空的SecurityContext(如果session中沒有SecurityContext實例),然後持久化到session中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章