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不满足要求,可以根据需求,修改对应的标头内容。
Cache control
security默认是禁止缓存,便于保护用户信息。如果应用有提供缓存控制的标头,security就不会管理cache。
content-type-options
这个是用于内容探测的,为了浏览器提高用户体验而设置的。
spring security中要使用角色:注意要使数据库中的角色前缀有ROLE_
java configuration
security java配置
首先创建配置,这个配置会创建一个称为springSeucurityFilterChain的servlet过滤器,该过滤器负责应用程序中的所有安全性。
@EnableWebSecurity
public class WebSecurityConfig implements WebMvcConfigurer {
//采取内存用户的方式
@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,确保过滤链注册。使用这个类根据是否使用spring的应用组件而异,这里只写spring的教程。
使用springMVC的AbstractSecurityWebApplicationInitializer
如果在程序的其他地方使用spring,则可能已经有一个initializer用来加载spring配置,如果使用要以前的配置,会得到一个错误,应该使用现有的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身份验证。
}
授权请求
可以添加多个子机到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是一个用户凭证接口作为用户认证的凭证使用,通常常用的实现有认证用户UsernamePasswordAuthentication和匿名用户AnonymousAuthenticationToken,Username中包含了UserDetails,AnonymousAuthenticationToken只包含了一个字符串anonymousUser作为匿名用户的标识。可以通过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,多用于多线程环境。
MODE_GLOBAL 静态机制,作用与全局,不太常用。