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

魚換水發表於2020-06-02

內容

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

相關文章