Spring Security 學習筆記 - 自動配置分析

創建項目

創建一個Springboot web項目,並寫一個簡單的hello控制器,其行爲只需要簡單返回一個響應即可,例如:

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public JsonResult hello() {
        return JsonResult.OK();
    }
}

運行它,請求 /hello,會返回響應,注意此時沒有任何權限機制對請求進行限制,也就是任何人都可以訪問/hello資源。

引入依賴

<dependency>
    <groupId>
        org.springframework.boot
    </groupId>
    <artifactId>
        spring-boot-starter-security
    </artifactId>
    <version>
        2.6.7
    </version>
</dependency>

默認加載

在引入Security後如果不做改動,Spring框架會在運行時自動加載Security並運行默認機制,效果就是Security會將整個項目請求保護起來。重新運行應用並訪問/hello,瀏覽器不再直接返回響應,而是跳轉到/login並顯示一個默認的登錄頁面,Security起作用了!

發生了什麼

Spring會自動加載Security默認安全機制,在請求發生後和Servlet處理請求前使用各種Filter處理這次請求,其中就包括Security框架所包含的Filter。下面代碼告訴了我們默認機制發生了什麼

 @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnDefaultWebSecurity
    static class SecurityFilterChainConfiguration {
        SecurityFilterChainConfiguration() {
        }

        @Bean
        @Order(2147483642)
        SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
            ((AuthorizedUrl)http.authorizeRequests().anyRequest()).authenticated();
            http.formLogin();
            http.httpBasic();
            return (SecurityFilterChain)http.build();
        }
    }

http的請求要開啓權限保護(authorizaRequests()),哪些請求要保護?任何請求(anyRequest()),這些請求都要是已認證的(authenticated),通過什麼方式認證,通過表單認證(formLogin())或Basic認證(httpBasic())——這是我基於教程的理解

註解@ConditionalOnDefaultWebSecurity是對defaultSecurityFilterChain方法在什麼條件下生效的聲明,進入註解看到

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({DefaultWebSecurityCondition.class})
public @interface ConditionalOnDefaultWebSecurity {
}

@Conditional註解說明ConditionalOnDefaultWebSecurity的使用條件是DefaultWebSecurityCondition,再進入DefaultWebSecurityCondition查看一下

class DefaultWebSecurityCondition extends AllNestedConditions {
    DefaultWebSecurityCondition() {
        super(ConfigurationPhase.REGISTER_BEAN);
    }

    @ConditionalOnMissingBean({WebSecurityConfigurerAdapter.class, SecurityFilterChain.class})
    static class Beans {
        Beans() {
        }
    }

    @ConditionalOnClass({SecurityFilterChain.class, HttpSecurity.class})
    static class Classes {
        Classes() {
        }
    }
}

DefaultWebSecurityCondition在兩種條件下生效,在當前類路徑中存在某些類定義的時候(@ConditionalOnClass)SecurityFilterChain.classHttpSecurity.class的時候,和(在現有工廠中)當不存在某些Bean的實例時候(@ConditionalOnMissingBean)不存在WebSecurityConfigurerAdapter.classSecurityFilterChain.class的時候。在引入依賴後,並沒有自己定義WebSecurityConfigurerAdapterSecurityFilterChain,因此剛纔的過濾鏈滿足了條件,起了作用,產生了效果。

總結一下,Security默認使用了defaultSecurityFilterChain(中的配置)進行安全行爲,如果希望改變默認行爲,需要自行定義WebSecurityConfigurerAdapterSecurityFilterChain。定義的方法是創建自己的類繼承並註解,使具體實現類在Spring容器中生效。Spring Security 推薦覆蓋WebSecurityConfigurerAdapter

bilibili - 編程不良人 - SpringSecurity最新實戰

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