八、【spring】web應用安全設計
阿新 • • 發佈:2020-06-03
> 內容
> - Spring Security
> - 使用Servlet規範中的Filter保護Web應用
> - 基於資料庫和LDAP進行認證
> 關鍵詞
## 8.1 理解Spring Security模組
> Spring Security:是為基於Spring的應用程式提供宣告式安全保護的安全性框架。Spring Security提供了完整的安全性解決方案,它能夠在Web請求級別和方法呼叫級別處理身份認證和授權。因為基於Spring框架,所以Spring Security充分利用了依賴注入(DI)和麵向切面的技術。
> 通過兩種角度解決安全問題
> 1. 使用Servlet規範中的Filter保護Web請求並限制URL級別的訪問。
> 2. 使用Spring AOP保護方法呼叫——藉助於物件代理和使用通知,能夠確保只有具備適當許可權的使用者才能訪問安全保護的方法。
### 8.1.1 理解模組
Security被分成以下11個模組
模組|描述
-|-
ACL|支援通過訪問控制列表(access control list,ACL)為域物件提供安全性
切面(Aspects)|一個很小的模組,當使用Spring Security註解時,會使用基於AspectJ的切面,而不是使用標準的Spring AOP
CAS客戶端(CAS Client)|提供與Jasig的中心認證服務(Central Authentication Service,CAS)進行整合的功能
配置(Configuration)|包含通過XML和Java配置Spring Security的功能支援
核心(Core)|提供Spring Security基本庫
加密(Cryptography)|提供了加密和密碼編碼功能
LDAP|支援基於LDAP進行認證
OpenID|支援使用OpenID進行集中式認證
Remoting|提供了對Spring Remoting的支援
標籤庫(Tag Library)|Spring Security的JSP標籤庫
Web|提供了Spring Security基於Filter的Web安全性支援
應用程式的類路徑下至少要包含Core和Configuration兩個模組
### 9.1.2 簡單的安全配置
Spring Security藉助Spring Filter來提高各種安全性功能
Spring Security配置
```java
package test
import .......Configuration;
import .......EnableWebSecurity;
import .......WebSecurityConfigureAdapter;
@Configuration
// 啟用Web安全性
@EnableWebSecurity
// 啟用Web MVC安全性
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigureAdapter {
}
```
以上只是寫了一個類擴充套件了WebSecurityConfigureAdapter類,但是要是啟用還需要過載WebSecurityConfigureAdapter的三個方法。
方法|描述
-|-
configure(WebSecurity)|通過過載,配置Spring Security的Filter鏈
configure(HttpSecurity)|通過過載,配置如何通過攔截器保護請求
configure(AuthenticationManageBuilder)|通過過載,配置user_detail服務
雖然過載了以上的方法,但是問題依然存在,我們需要
- 配置使用者儲存
- 指定那些請求需要認證,哪些不需要,以及提供什麼樣的許可權
- 提供一個自定義的登陸頁面,替代原來簡單的預設登入頁
## 8.2 選擇查詢使用者詳細資訊的服務
> Spring Security提供了基於資料儲存來認證使用者,它內建了多種常見的使用者儲存場景,如記憶體,關係型資料庫以及LDAP,也可以編寫並插入自定義的使用者儲存實現。
### 8.2.1 使用基於記憶體的使用者儲存
擴充套件了WebSecurityConfigureAdapter,所以過載Configure方法,並以AuthenticationManageBuilder作為傳入引數
```java
package test.config
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManageBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER").and().withUser("admin").password("password").roles(""USER","ADMIN");
}
}
```
程式碼解析:
- configure()方法中使用類使用構造者風格的介面來構建認證配置。
- 呼叫withUser()方法為記憶體使用者儲存新增新的使用者,該方法的UserDetailsManagerConfigurer.UserDetailsBuilder,
- 新增兩個使用者,user具有USER角色,admin具有USER和ADMIN角色。
- roles方法是authorities方法的簡寫形式。
配置使用者詳細資訊的方法
方法|描述
-|-
accountExpired(boolean)|定義賬號是否過期
accountLocked(boolean)|定義賬號是否已經鎖定
and()|用來連線配置
authorities(GrantedAuthority)|授予某個使用者一項或多項許可權
authorities(List)|授予某個使用者一項或多項許可權
authorities(string ....)|授予某個使用者一項或多項許可權
credentialsExpired(boolean)|定義憑證是否已經過期
disabled(boolean)|定義賬號是否被禁用
password(String)|使用者定義的密碼
roles(String ...)|授予某個使用者一項或多項角色
## 8.3 攔截請求
> 請求不是不攔截,也不是都攔截,而是需要適度的攔截
```java
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/spitters/me").authenticated().antMatchers(HttpMethod.POST,"/spittles").authenticated().anyRequest().permitAll();
}
```
保護路徑配置方法列表
方法|描述
-|-
access(String)|如果給定的SpEL表示式計算結果為True,就允許訪問
anonymous()|允許匿名使用者訪問
authenticated()|允許認證過的使用者訪問
denyAll()|無條件拒絕所有訪問
fullyAuthenticated()|如果使用者是完整認證的話,就允許訪問
hasIpAddress(String)|如果請求來自給定IP,允許
hasRole(String)|如果使用者具備給定角色的話,就允許
not()|對其他訪問求反
permitAll()|無條件允許訪問
rememberMe()|如果使用者是通過Remember-me功能認證的,允許
### 8.3.1 強制通道安全性
> 使用requireChannel()方法,藉助這個方法可以為各種URL模式宣告所請求的通道
```java
```java
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/spitters/me").authenticated().antMatchers(HttpMethod.POST,"/spittles").authenticated().anyRequest().permitAll().and().requiresChannel().antMatchers("/spitters/form").requireSecure();<--需要HTTPS
.requiresInsecure().antMatchers("/").requireInSecure();<--使用HTTP
}
```
### 8.3.2 防止跨站請求偽造
> 跨站請求偽造(cross-site request forgery,CSRF)
Spring Security通過一個同步token的方式來實現CSRF防護的功能。它將會攔截狀態變化的請求(非GET、HEAD等的請求)並檢查CSRF_token。如果請求中不包含CSRF token或者與伺服器的token不符合則會失敗,並丟擲csrfException異常。意味著在所有表單中必須在一個"_csrf"的域中提交token
```html
...
```
當然也可以在程式碼中取消該功能
.csrf.disable()