Spring Security的使用 #Web安全#權限認證《Spring實戰》第4版筆記 (二)

9.3 攔截請求

對每個請求進行細粒度安全性控制的關鍵在於重載configure(HttpSecurity) 方法。如下代碼中的重載configure,爲不同的URL路徑有選擇性的應用安全性

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http.authorizeRequests()
                .antMatchers("/test1").authenticated() //對路徑認證
                .antMatchers(HttpMethod.POST,"/test2").authenticated() //對路徑的POST請求認證
                .anyRequest().permitAll(); //方通其他路徑請求,不需要認證和任何的權限
    }	

除了路徑選擇,還可以通過authenticated() 和 permitAll() 來定義該如何保護路徑。authenticated()要求在執行該請求時,必須已經登錄了應用。如果用戶沒有認證的話,Spring Security的Filter將會捕獲該請求,並將用戶重定向到應用的登錄界面。

其他的用來定義如何保護請求的方法

方法 能夠做什麼
access(String) 如果給定的SpEL表達式計算結果爲true,就允許訪問
anonymous() 允許匿名訪問
authenticated() 允許認證過的用戶訪問
denyAll() 無條件拒絕訪問
fullyAuthenticated() 如果用戶是完整認證的話(不是通過Remember-me功能認證的),就允許訪問
hasAnyAuthority(String…) 如果用戶具備給定權限的某一個的話,就允許訪問
hashAnyRole(String…) 如果用戶具備給定角色的某一個的話,就允許訪問
hashAuthority(String) 如果用戶具備給定權限的話,就允許訪問
hasIpAddress(String) 如果請求來自給定IP地址的話,就允許訪問
hasRole(String) 如果用戶具備給定角色的話,就允許訪問
not() 對其他訪問方法的結果求反
permitAll() 無條件訪問
rememberMe() 如果用戶是通過Remember-me功能認證的,就允許訪問

可以將任意數量的 antMatchers()、regexMatchers()和anyRequest()連接起來,以滿足Web應用安全規則的需要,但是!這些規則會按照給定的順序發揮作用。所以 要將最爲具體的請求路徑放在前面,而最不具體的路徑(如anyRequest())放在最後面。

9.3.1 SpringEL進行安全保護

SpringEL具有強大的多維度保護機制。它能支持很多SpEL表達式

.antMatchers("/test1").access("hasRole('ROLE_USER')")  //具有ROLE_USER角色才能訪問的url
安全表達式 計算結果
authentication 用戶的認證對象
denyAll 結果始終爲false
hasAnyRole(list of roles) 如果用戶被授予了列表中的指定角色,結果爲true
hashRole(role) 如果用戶被授予了指定的角色,結果爲true
hasIpAddress(IP Address) 如果請求來自指定IP的話,結果爲true
isAnonymous() 如果當前用戶爲匿名用戶,結果爲true
isAuthenticated() 如果當前用戶進行了認證,結果爲true
ifFullyAuthenticated() 如果當前用戶進行了完整的認證的話,結果爲true
isRememberMe() 如果當前用戶是通過Remember-me自動認證的,結果爲true
permitAll 結果始終爲true
principal 用戶的principal對象
.antMatchers("/test1")
 .access("hashRole('ROLE_USER') and hasIpAddress('192.168.1.1') ") //指定權限且來自指定的IP

9.3.2 強制通道的安全性

藉助requiresChannel()方法,能夠爲各種URL模式聲明所要求的通道。

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http.authorizeRequests()
                .antMatchers("/test1").hasRole("USER")//對路徑認證
                .antMatchers(HttpMethod.POST,"/test2").hasRole("USER") //對路徑的POST請求認證
                .anyRequest().permitAll() //方通其他路徑請求,不需要認證和任何的權限
        .and()
                .requiresChannel()
                .antMatchers("/test1/test3").requiresSecure(); //需要HTTPS
                //.antMatchers("/").requiresInecure(); 始終通過HTTP傳送
    }	

此時,只要是對 /test1/test3 的請求,Spring Security都視爲需要安全通道並自動將請求重定向到HTTPS上。

9.3.3 防止跨站請求僞造

跨站請求僞造(CSRF):如果一個站點欺騙用戶提交請求到其他服務器,即CSRF攻擊。

不去處理的方式:httpSecurity.csfr().disable(); //禁用CSRF防護功能

9.4 認證用戶

9.4.1 添加自定義的登錄頁

9.4.2 啓用HTTP Basic認證

HTTP Basic認證(HTTP Basic Authentication)會直接通過HTTP請求本身,對訪問應用程序的用戶進行認證。在REST客戶端向它使用的服務進行認證的場景中,這種方式比較適合。

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http
                .csrf().disable()
                .formLogin()  //啓用默認的登錄頁
                .and()
                .httpBasic().realmName("Spittr")  //啓用HTTP Basic認證
            ....
    }

9.4.3 啓用Remember-me

只要登陸過一次,應用程序就會記住你,當再次回到應用的時候就不需要登錄了,啓用方式:在configure()方法傳入的HttpSecurity對象上調用rememberMe( )即可。

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http
                .csrf().disable()
                .formLogin()  //啓用默認的登錄頁
                .and()
                .httpBasic().realmName("Spittr")  //啓用HTTP Basic認證
                .and()
                .rememberMe()
                   .tokenValiditySeconds(2419200)
                   .key("spitterKey")
            ....
    }

默認情況下,這個功能是通過在cookie中存儲一個token完成的,這個token最多兩週內有效。但是,在這裏,我們制定token最多四周內有效(2419200秒)。存儲在cookie中的token包含用戶名、密碼、過期時間和一個私鑰—在寫入cookie前都進行了MD5哈希。默認情況下,私鑰的名爲SpringSecured,可以自己命名使它用於Spittr應用。

9.4.4 退出

退出功能是通過Servlet容器中的Filter實現的(默認情況下),這個Filter會攔截針對"/logout"的請求。因此只要發起對"/logout"的請求,就會被Spring Security的LogoutFilter所處理,用戶會退出應用,所有的Remember-me token都會被清除掉。在退出完成後,用戶瀏覽器將會重定向到"/login?logout",從而允許用戶進行再次登錄。

可以通過在configure()配置,重定向指定頁面

@Override
protected void configure(HttpSecurity http) throws Exception{
    http
      .formLogon()
      .and()
      .logout()
         .logoutSuccessUrl("/")  //重定向到"/"
         .logoutUrl("/signout")  //重寫默認的LogoutFilter攔截路徑
}

9.5 保護視圖

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