八、【spring】web應用安全設計
內容
- 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();即可