內容
- Spring Security
- 使用Servlet規範中的Filter保護Web應用
- 基於資料庫和LDAP進行認證
關鍵詞
8.1 理解Spring Security模組
Spring Security:是為基於Spring的應用程式提供宣告式安全保護的安全性框架。Spring Security提供了完整的安全性解決方案,它能夠在Web請求級別和方法呼叫級別處理身份認證和授權。因為基於Spring框架,所以Spring Security充分利用了依賴注入(DI)和麵向切面的技術。
通過兩種角度解決安全問題
- 使用Servlet規範中的Filter保護Web請求並限制URL級別的訪問。
- 使用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配置
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作為傳入引數
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<? extends grantedAuthority>) | 授予某個使用者一項或多項許可權 |
authorities(string ....) | 授予某個使用者一項或多項許可權 |
credentialsExpired(boolean) | 定義憑證是否已經過期 |
disabled(boolean) | 定義賬號是否被禁用 |
password(String) | 使用者定義的密碼 |
roles(String ...) | 授予某個使用者一項或多項角色 |
8.3 攔截請求
請求不是不攔截,也不是都攔截,而是需要適度的攔截
@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
@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
<form method="POST" th:action="@{/spittle}">
...
</form>
當然也可以在程式碼中取消該功能
.csrf.disable();即可