spring security學習
security HTTP response headers
如果需要時,security可以自己配置對應headers
默認headers
security默認headers包含以下標頭
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
如果默認headers不滿足要求,可以根據(jù)需求,修改對應的標頭內(nèi)容。
Cache control
security默認是禁止緩存,便于保護用戶信息。如果應用有提供緩存控制的標頭,security就不會管理cache。
content-type-options
這個是用于內(nèi)容探測的,為了瀏覽器提高用戶體驗而設置的。
spring security中要使用角色:注意要使數(shù)據(jù)庫中的角色前綴有ROLE_
java configuration
security java配置
首先創(chuàng)建配置,這個配置會創(chuàng)建一個稱為springSeucurityFilterChain的servlet過濾器,該過濾器負責應用程序中的所有安全性。
@EnableWebSecurity
public class WebSecurityConfig implements WebMvcConfigurer {
//采取內(nèi)存用戶的方式
@Bean
public UserDetailsService userDetailsService() throws Exception {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
return manager;
}
}
下一步是向war注冊springSecurityFilterChain。security提供一個BaseclassAbstractSecurityWebApplicationInitializer,確保過濾鏈注冊。使用這個類根據(jù)是否使用spring的應用組件而異,這里只寫spring的教程。
使用springMVC的AbstractSecurityWebApplicationInitializer
如果在程序的其他地方使用spring,則可能已經(jīng)有一個initializer用來加載spring配置,如果使用要以前的配置,會得到一個錯誤,應該使用現(xiàn)有的context注冊spring security,如使用springmvc時,則SecurityWebApplicationInitializer如下所示
import org.springframework.security.web.context.*;
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}
HttpSecurity
在WebSecurityConfigurerAdapter的configure(HttpSecurity http)方法中提供了默認配置,如下
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests() //開啟身份驗證
.anyRequest().authenticated()//任何請求都需要驗證
.and()
.formLogin()
.and()
.httpBasic(); //允許用戶使用HTTP Basic身份驗證。
}
授權(quán)請求
可以添加多個子機到http.authorizeRequests方法中來為URL指定自定義要求
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/signup", "/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.anyRequest().authenticated()
.and()
// ...
.formLogin();
}
任何以“/admin/”開頭的url都限定于ROLE_ADMIN的用戶,由于使用了hasRole方法,無需指定ROLE_前綴,其余同理。
處理注銷
默認設置是訪問/logout,將通過以下方式注銷用戶,和登錄功能配置類似都是可以自己配置的
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutUrl("/my/logout")
.logoutSuccessUrl("/my/index")
.logoutSuccessHandler(logoutSuccessHandler)
.invalidateHttpSession(true)
.addLogoutHandler(logoutHandler)
.deleteCookies(cookieNamesToClear)
.and()
...
}
安全上下文
spring security會將認證的用戶信息封裝到UsernamePasswordAuthenticationToken中,然后將這個封裝信息放入安全上下文中,當服務端響應用戶后又使用同一個工具類從SecurityContext中clear掉。
package org.springframework.security.core.context;
import java.io.Serializable;
import org.springframework.security.core.Authentication;
public interface SecurityContext extends Serializable {
Authentication getAuthentication();
void setAuthentication(Authentication var1);
}
源碼中就只有兩個方法。securitycontext是一個存儲Authentication的容器,而Authentication是一個用戶憑證接口作為用戶認證的憑證使用,通常常用的實現(xiàn)有認證用戶UsernamePasswordAuthentication和匿名用戶AnonymousAuthenticationToken,Username中包含了UserDetails,AnonymousAuthenticationToken只包含了一個字符串a(chǎn)nonymousUser作為匿名用戶的標識。可以通過SecurityContext判斷是操作匿名的token還是username。
SecurityContextHolder
這是工具類,提供了的方法中有三個比較重要,clearContext:清除當前的SecurityContext;getContext:獲取當前的SecurityContext;setContext:設置當前的context。
例子如下
public String getUser(){
Authentication auth = SecuriyContextHolder.getContext().getAuthentication();
if(auth instanceof AnonymousAuthentication){
return "anonymous";
}
UserDetails principal =(UserDetails) authencation.getPrincipal();
return principal.getUsername();
}
SecurityContextHolder的存儲策略
holder默認有三種存儲context的策略
MODE_THREADLOCAL 使用ThreadLocal機制來保存每個使用者的context,缺省策略
MODE_INHERITABLETHREADLOCAL 利用InheritableThreadLocal機制來保存每個使用者的context,多用于多線程環(huán)境。
MODE_GLOBAL 靜態(tài)機制,作用與全局,不太常用。