八、【spring】web應用安全設計

內容

  • 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配置

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();即可

Tags: