Spring Security 通過創建一個 FilterChainProxy 的實例來實現所有功能,FilterChainProxy 是所有 Spring Security 功能的入口,一旦 FilterChainProxy 初始化完成,Spring Security 啟動也就完成了。FilterChainProxy 實現 Filter 接口,因此 FilterChainProxy 就是一個過濾器,因而可以將 Spring Security 理解為一個過濾器。
FilterChainProxy功能點入口
在 Spring Security 的 spring-security-web 模塊中,FilterChainProxy 在包 org.springframework.security.web 下。
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { boolean clearContext = request.getAttribute(FILTER_APPLIED) == null; if (clearContext) { try { request.setAttribute(FILTER_APPLIED, Boolean.TRUE); doFilterInternal(request, response, chain); } finally { SecurityContextHolder.clearContext(); request.removeAttribute(FILTER_APPLIED); } } else { doFilterInternal(request, response, chain); } }
上面這個方法是 FilterChainProxy 功能點的入口,當請求到達調用 controller 層之前,會被 FilterChainProxy 攔截,然后進入上面所示的 doFilter 方法,因而如果要調試 Spring Security 在此方法上打斷點是最好的。
FilterChainProxy初始化過程
既然 Spring Security 一切功能點都是從 FilterChainProxy 開始,因而當項目啟動時,FilterChainProxy 的實例也創建完成了。FilterChainProxy 實例是如何被創建的?
- 當在 Spring Boot 項目中添加了 Spring Security 依賴后,在 spring-boot-autoconfigure.jar 中 org.springframework.boot.autoconfigure.security.servlet 包中有個 SecurityAutoConfiguration 類,這就是當項目引入 Spring Security 后 Spring Boot 會啟用的安全配置類。
- 在 SecurityAutoConfiguration 類上的 @Import 注解引入了 WebSecurityEnablerConfiguration 類。
- 在 WebSecurityEnableConfiguration 上有個注解 @EnableWebSecurity。
- 查看注解 @EnableWebSecurity 源碼,可以看到其又通過 @Import 注解引入了 WebSecurityConfiguration 類。
在 WebSecurityConfiguration 中有兩個十分重要的方法,分別是:
- setFilterChainProxySecurityConfigurer(...) 此方法會創建一個 WebSecurity 實例
- springSecurityFilterChain() 此方法會調用上一步產生的 WebSecurity 的 build() 方法,而 webSecurity.buid() 方法返回一個 FilterChainProxy 實例。
至此,FilterChainProxy 初始化就完成了。
上面是 Spring Security 啟動時的簡易初始步驟。