天天看點

Spring Security 實戰(使用Spring Boot項目示範)

Spring Security 的應用越來越廣泛,它支援頁面級别、API級别 以及方法級别的權限控制,可以說項目中的絕大部分場景都能适用。不管哪種級别的權限控制,都需要進行以下的步驟 (使用Spring Boot項目示範):

1. 加入Spring Boot Security的依賴 (不需要版本号,因為Spring boot的parent pom裡面就已經有版本号了):

compile "org.springframework.boot:spring-boot-starter-security"

2. 啟動類加注解

注意這裡有個地雷,我不小心踩到過,如果你的Spring Boot版本比較低的話,切記要加上@ComponentScan注解,不然你會遇到綿綿不斷的缺少各種依賴,能煩死。

@EnableGlobalMethodSecurity(prePostEnabled = true) 這個注解隻是在你需要使用方法級别的權限認證的時候需要加的,否則可以不加。

Spring Security 實戰(使用Spring Boot項目示範)

3. 新加一個繼承了WebSecurityConfigurerAdapter的配置類,這可以說是Spring Security的核心了,我們可以在這個類裡面配置使用者權限,過濾器,認證管理器,攔截路徑等。

需要加上@Configuration注解和@EnableWebSecurity注解

Spring Security 實戰(使用Spring Boot項目示範)

3.1. 在SecurityConfig中配置使用者角色權限:

可以直接在啟動的時候直接hard-coding方式将使用者角色初始化到記憶體中;

也可以通過DataSource從資料庫抓取使用者角色資訊;

另外還可以通過解析request裡面的username & password動态的給使用者配置設定角色權限。

Spring Security 實戰(使用Spring Boot項目示範)

3.2. 在SecurityConfig中配置路徑攔截

配置路徑和通路權限可以參考Spring Security的官方文檔,大緻簡單介紹一下:

這個配置方式有點類似構模組化式,一步步去建構HttpSecurity對象。

authorizeRequests()這個表示擷取URL注冊對象,得到這個對象之後可以進行一些URL比對操作

antMatchers() 這個表示使用Ant格式來比對路徑,也就意味着你可以使用Ant裡面的通配符

hasRole() 很明顯,有參數裡面指定的角色才可以通路這個路徑

access() 參數裡面是一個Spring EL表達式,隻有當表達式傳回true才允許通路

anyRequest() 表示所有請求,類似AntMathchers(“/**”) 注意這個放到後面,如果放到前面,會覆寫掉前面指定的哪些具體路徑

permitAll() 無條件讓所有請求通過

denyAll() 無條件讓所有請求不通過

上面這個配置的意思是首先禁用csrf,然後如果通路useraccess API需要有USER權限,如果通路 adminaccess API需要有ADMIN權限,其他的一律讓它們通過,不做判斷。

4. 對應的頁面,API或方法:

上面示範的這種适用于頁面或API,因為是在配置裡面通過路徑去指定的,下面還要介紹一個方法級别的控制。

如果要加入方法級别的權限認證(當然,方法級别的也同樣可以控制使用者通路API,畢竟在Spring架構中 API是定義在方法上面的),那麼:

1. 首先需要在啟動類中加入@EnableGlobalMethodSecurity(prePostEnabled = true)這個注解。

2. 同樣可以像上面介紹的那樣在SecurityConfig裡面去配置使用者及使用者的角色,當然更靈活的我們可以自己去定義适用于每個request的使用者角色:

這是使用者角色Bean,我自己定義它有一個hasRole方法,你也可以定義别的方法,隻要到時候在方法上面的條件表達式能判斷即可

在上面那個SecurityConfig裡面配置下這個使用者角色的Bean,注意我這裡将Bean的作用域定義成Request,也就是每個request過來都會建立一個新的Bean,而不是預設的單例Bean。這樣我就可以根絕每個request帶過來的資訊初始化這個Bean 并為之授予相應的權限了。這裡為了示範簡單,我直接初始化的。

另外,也可以加一個AccessDeniedHandler配置,自己定義當方法禁止通路時傳回的消息:

在SecurityConfig中配置一下這個AccessDeniedHandler才會起作用:

3. 好了,接下來可以在方法上加入@PreAuthorize注解,裡面定義一個表達式,隻要結果傳回true就可以通路這個方法,否則會走剛才定義的AccessDeniedHandle傳回錯誤消息。

要先注入這個UserAccess Bean哦。

網絡上志同道合,我們一起學習網絡安全,一起進步,QQ群:694839022