文章目录
- 基础的一些类及其作用
- 自定义配置类入口WebSecurityConfigurerAdapter
- 2.1 认证管理器配置方法
- 2.2 核心过滤器配置方法
- 2.3 安全过滤器链配置方法
- 3. HttpSecurity 配置
异步:当http请求进来的时候,开启一个副线程,在副线程中处理,然后处理后再将结果给主线程返回,在此期间主线程可以处理其他请求。
官方文档中说DeferredResult和Callable都是为了异步生成返回值提供基本的支持。简单来说就是一个请求进来,如果你使用了DeferredResult或者Callable,在没有得到返回数据之前,DispatcherServlet和所有Filter就会退出Servlet容器线程,但响应保持打开状态,一旦返回数据有了,这个DispatcherServlet就会被再次调用并且处理,以异步产生的方式,向请求端返回值。
这么做的好处就是请求不会长时间占用服务连接池,提高服务器的吞吐量。使用Callable和DeferredResult,提高服务性能DispatchServlet请求处理流程源码解析
核心功能:认证(你是谁),授权(你能干什么),攻击防护(放置伪造身份)。
基础的一些类及其作用
1.处理用户信息获取逻辑(UserDetailsService):去实现-抽象类UserDetailService中的loadUserByUsername
.返回的是UserDetail的一个实现类。
2.处理用户校验逻辑(userDetails):通过它的一个实现类中的方法,去校验。
3.处理加密和解密(PassWordEncoder):passwordEncoder中的encode():用来加密存入到数据库.match()进行匹配。
@Bean
public PasswordEncoder passwordEncode(){
return new BCryptPasswordEncoder();
}
4.自定义登录页面:http.formLogin().loginPage("/wu-signIn.html);
5.自定义登录成功处理:AuthenticationSuccessHandler
6.自定义登录失败处理:AuthenticationFailureHandler
http
.authorizeRequests() 1
.antMatchers( "/resources/**", "/signup" , "/about").permitAll() 2
.antMatchers( "/admin/**").hasRole("ADMIN" ) 3
.antMatchers( "/db/**").access("hasRole('ADMIN') and hasRole('DBA')") 4
.anyRequest().authenticated() 5
.and()
// ...
.formLogin();
}
antMatchers方法来定义什么样的请求可以放过,什么样的请求需要验证
1、http.authorizeRequests()方法有很多子方法,每个子匹配器将会按照声明的顺序起作用。
2、指定用户可以访问的多个url模式。特别的,任何用户可以访问以"/resources"开头的url资源,或者等于"/signup"或about
3、任何以"/admin"开头的请求限制用户具有 "ROLE_ADMIN"角色。你可能已经注意的,尽管我们调用的hasRole方法,但是不用传入"ROLE_"前缀
4、任何以"/db"开头的请求同时要求用户具有"ROLE_ADMIN"和"ROLE_DBA"角色。
5、任何没有匹配上的其他的url请求,只需要用户被验证。
SpringSecurity框架的原理流程图: 源码解析参考文章。
流程步骤:
1.密码登录请求给UsernamePasswordAuthenticationFilter
,此过滤器将用户名和密码拿出来组装成UsernamePsswordAuthenticationToken
(未认证)对象。具体的源码认证过程在Spring Security课程文档中
2.然后将它传给AuthenticationManager
,从这个类中一堆的Authenticationprovider中挑选一个provider来处理这个认证请求。而挑选的依据是provider里面有一个support方法,用support方法判断是否支持当前传递进来的Token,如果支持的话,就会选择。
3.在认证的过程中会用UserDetailService
去获取用户的信息,跟传进来登录信息,进行判断和比对,然后最后进行判断是否认证通过。如果认证通过。将token做一个标志。标记为(已认证)放到session中。
UsernamePasswordAuthenticationFilter
:如果请求中没有用户名和密码会直接放过,并且由下图可以看出,它只会处理“/login”的post请求,请他请求都放过。绿色的过滤器可以通过配置决定在不在过滤器链上,而蓝色和红色的过滤器一定在该位置上。
FilterSecurityInterceptor:处于过滤器链上的最后一环。所有的最后的判断逻辑在2中进行判断判断放不放过。;而后面的doFilter,表示可以直接访问RestFul了。
用户的信息获取逻辑在UserDetailsService
中,然后只有一个方法loadUserByUsername
,并且只能接受一个String类型的参数,一般就是用户名,username
。就是根据用户通过表单输入的用户名到相应的数据库中查询数据,然后将数据封装到UserDetails接口中具体的一个实现类。
SecurityContextPersisenceFiter:是过滤器链上的第一个过滤器的作用:
1.当请求进来的时候检查session中是否有SecurityContext,如果有就把SecurityContext拿出来放入到线程里。
2.当请求回来的时候检查线程中有SecurityContext,就把SecurityContext放入到session中去。
securityContextHolder使用了ThreadLocal机制来保存每个使用者的安全上下文。这意味着,只要针对某个使用者的逻辑执行都是在同一个线程中进行,即使不在各个方法之间以参数的形式传递其安全上下文,各个方法也能通过SecurityContextHolder工具获取到该安全上下文。
Authentication对象:用来描述当前用户的相关信息,Spring Security会自动为我们创建相应的Authentication对象,然后赋值给当前的SecurityContext。
SecurityContext:安全上下文,即存储认证授权的相关信息,代表当前用户相关信息的Authentication的引用。实际上就是存储"当前用户"账号信息和相关权限。这个接口只有两个方法,获取和设置Authentication对象的getter、setter方法。
自定义配置类入口WebSecurityConfigurerAdapter
@Configuration
@ConditionalOnClass(WebSecurityConfigurerAdapter.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class CustomSpringBootWebSecurityConfiguration {
@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER)
static class DefaultConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
}
}
}
相信已经有人注意到了上面 DefaultConfigurerAdapter 中我覆写(@Override)了三个方法,我们一般会通过自定义配置这三个方法来自定义我们的安全访问策略。
2.1 认证管理器配置方法
void configure(AuthenticationManagerBuilder auth)
用来配置认证管理器AuthenticationManager。说白了就是所有 UserDetails 相关的它都管,包含 PasswordEncoder 密码机。如果你不清楚可以通过 Spring Security 中的 UserDetail 进行了解。本文对 AuthenticationManager 不做具体分析讲解,后面会有专门的文章来讲这个东西 。 可通过 Spring Security 实战系列 进行学习。
2.2 核心过滤器配置方法
void configure(WebSecurity web)
用来配置 WebSecurity 。而 WebSecurity 是基于 Servlet Filter 用来配置 springSecurityFilterChain 。而 springSecurityFilterChain 又被委托给了 Spring Security 核心过滤器 Bean DelegatingFilterProxy 。 相关逻辑你可以在 WebSecurityConfiguration 中找到。我们一般不会过多来自定义 WebSecurity , 使用较多的使其ignoring() 方法用来忽略 Spring Security 对静态资源的控制。
2.3 安全过滤器链配置方法
void configure(HttpSecurity http)
这个是我们使用最多的,用来配置 HttpSecurity 。 HttpSecurity 用于构建一个安全过滤器链 SecurityFilterChain 。SecurityFilterChain 最终被注入核心过滤器 。 HttpSecurity 有许多我们需要的配置。我们可以通过它来进行自定义安全访问策略。所以我们单独开一章来讲解这个东西。
3. HttpSecurity 配置
HttpSecurity 是后面几篇文章的重点,我们将实际操作它来实现一些实用功能。所以本文要着重介绍它。
protected void configure(HttpSecurity http) throws Exception {
logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();
}
上面是 Spring Security 在 Spring Boot 中的默认配置。通过以上的配置,你的应用具备了一下的功能:
- 所有的请求访问都需要被授权。
- 使用 form 表单进行登陆(默认路径为/login),也就是前几篇我们见到的登录页。
- 防止 CSRF 攻击、 XSS 攻击。
- 启用 HTTP Basic 认证