Spring Security是一款基於Spring的安全框架,主要包含認證和受權兩大安全模塊,和另一款流行的安全框架Apache Shiro相比,它擁有更爲強大的功能。Spring Security也能夠輕鬆的自定義擴展以知足各類需求,而且對常見的Web安全攻擊提供了防禦支持。若是你的Web框架選擇的是Spring,那麼在安全方面Spring Security會是一個不錯的選擇。web
這裏咱們使用Spring Boot來集成Spring Security,Spring Boot版本爲1.5.14.RELEASE,Spring Security版本爲4.2.7RELEASE。spring
建立一個Spring Boot項目,而後引入spring-boot-starter-security:瀏覽器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
接下來咱們建立一個TestController,對外提供一個/hello服務:安全
@RestController
public class TestController {
@GetMapping("hello")
public String hello() {
return "hello spring security";
}
}
這時候咱們直接啓動項目,訪問http://localhost:8080/hello,可看到頁面彈出了個HTTP Basic認證框:app
當Spring項目中引入了Spring Security依賴的時候,項目會默認開啓以下配置:框架
security:
basic:
enabled: true
這個配置開啓了一個HTTP basic類型的認證,全部服務的訪問都必須先過這個認證,默認的用戶名爲user,密碼由Sping Security自動生成,回到IDE的控制檯,能夠找到密碼信息:ide
Using default security password: e9ed391c-93de-4611-ac87-d871d9e749ac
輸入用戶名user,密碼e9ed391c-93de-4611-ac87-d871d9e749ac後,咱們即可以成功訪問/hello接口。spring-boot
咱們能夠經過一些配置將HTTP Basic認證修改成基於表單的認證方式。spa
建立一個配置類BrowserSecurityConfig繼承org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter這個抽象類並重寫configure(HttpSecurity http)方法。WebSecurityConfigurerAdapter是由Spring Security提供的Web應用安全配置的適配器:debug
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 表單方式
.and()
.authorizeRequests() // 受權配置
.anyRequest() // 全部請求
.authenticated(); // 都須要認證
}
}
Spring Security提供了這種鏈式的方法調用。上面配置指定了認證方式爲表單登陸,而且全部請求都須要進行認證。這時候咱們重啓項目,再次訪問http://localhost:8080/hello,能夠看到認證方式已是form表單的方式了:
用戶名依舊是user,密碼由Spring Security自動生成。當輸入憑證錯誤時,頁面上將顯示錯誤信息:
若是須要換回HTTP Basic的認證方式,咱們只須要簡單修改configure方法中的配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.formLogin() // 表單方式
http.httpBasic() // HTTP Basic方式
.and()
.authorizeRequests() // 受權配置
.anyRequest() // 全部請求
.authenticated(); // 都須要認證
}
上面咱們開啓了一個最簡單的Spring Security安全配置,下面咱們來了解下Spring Security的基本原理。經過上面的的配置,代碼的執行過程能夠簡化爲下圖表示:
如上圖所示,Spring Security包含了衆多的過濾器,這些過濾器造成了一條鏈,全部請求都必須經過這些過濾器後才能成功訪問到資源。其中UsernamePasswordAuthenticationFilter過濾器用於處理基於表單方式的登陸認證,而BasicAuthenticationFilter用於處理基於HTTP Basic方式的登陸驗證,後面還可能包含一系列別的過濾器(能夠經過相應配置開啓)。在過濾器鏈的末尾是一個名爲FilterSecurityInterceptor的攔截器,用於判斷當前請求身份認證是否成功,是否有相應的權限,當身份認證失敗或者權限不足的時候便會拋出相應的異常。ExceptionTranslateFilter捕獲並處理,因此咱們在ExceptionTranslateFilter過濾器用於處理了FilterSecurityInterceptor拋出的異常並進行處理,好比須要身份認證時將請求重定向到相應的認證頁面,當認證失敗或者權限不足時返回相應的提示信息。
下面咱們經過debug來驗證這個過程(登陸方式改回表單的方式)。
咱們在/hello服務上打個斷點:
在FilterSecurityInterceptor的invoke方法的super.beforeInvocation上打個斷點:
當這行代碼執行經過後,即可以調用下一行的doFilter方法來真正調用/hello服務,不然將拋出相應的異常。
當FilterSecurityInterceptor拋出異常時,異常將由ExceptionTranslateFilter捕獲並處理,因此咱們在ExceptionTranslateFilter的doFilter方法catch代碼塊第一行打個斷點:
咱們待會模擬的是用戶未登陸直接訪問/hello,因此應該是拋出用戶未認證的異常,因此接下來應該跳轉到UsernamePasswordAuthenticationFilter處理表單方式的用戶認證。在UsernamePasswordAuthenticationFilter的attemptAuthentication方法上打個斷點:
準備完畢後,咱們啓動項目,而後訪問http://localhost:8080/hello,代碼直接跳轉到FilterSecurityInteceptor的斷點上:
往下執行,由於當前請求沒有通過身份認證,因此將拋出異常並被ExceptionTranslateFilter捕獲:
捕獲異常後重定向到登陸表單登陸頁面,當咱們在表單登陸頁面輸入信息點login後,代碼跳轉到UsernamePasswordAuthenticationFilter過濾器的attemptAuthentication方法上:
判斷用戶名和密碼是否正確以後,代碼又跳回FilterSecurityInterceptor的beforeInvocation方法執行上:
當認證經過時,FilterSecurityInterceptor代碼往下執行doFilter,而後代碼最終跳轉到/hello上:
瀏覽器頁面將顯示hello spring security信息。