- 一、过滤器链
- FilterSecurityInterceptor
- ExceptionTranslationFilter
- UsernamePasswordAuthenticationFilter
- 二、过滤器加载过程
- 三、两个重要的接口
- UserDetailsService
- PasswordEncoder
SpringSecurity 本质是一个过滤器链:
从启动是可以获取到过滤器链:
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter org.springframework.security.web.context.SecurityContextPersistenceFilter org.springframework.security.web.header.HeaderWriterFilter org.springframework.security.web.csrf.CsrfFilter org.springframework.security.web.authentication.logout.LogoutFilter org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter org.springframework.security.web.savedrequest.RequestCacheAwareFilter org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter org.springframework.security.web.authentication.AnonymousAuthenticationFilter org.springframework.security.web.session.SessionManagementFilter org.springframework.security.web.access.ExceptionTranslationFilter org.springframework.security.web.access.intercept.FilterSecurityInterceptorFilterSecurityInterceptor
一个方法级的权限过滤器,基本位于过滤器链的最底部
此类实现了Filter接口,说明是一个过滤器
在doFilter()方法中执行了invoke()方法
异常过滤器,用来处理在认证授权过程中抛出的异常
在doFilter()方法中放行,在handleSpringSecurityException()方法中对不同的异常进行处理
对/login的 POST 请求做拦截,校验表单中用户名和密码。
attemptAuthentication()方法根据post请求中的用户名密码进行校验
往上看,UsernamePasswordAuthenticationFilter类是继承了抽象类AbstractAuthenticationProcessingFilter
在抽象类AbstractAuthenticationProcessingFilter中可以看到两个方法,上面的方法是用户名和密码认证成功后执行的代码,下面的则是认证失败执行的代码,所以在UsernamePasswordAuthenticationFilter过滤器中,登录认证成功或失败都会默认调用父类的方法
- 使用SpringSecurty配置过滤器,也就是SpringBoot项目中自动配置的DelegatingFilterProxy类
而在doFilter()方法各种判断过后调用了initDelegate()方法,在该方法里可以获取到FilterChainProxy对象
- 在FilterChainProxy也会进入doFilter()方法,然后再进行各种判断后,会进入doFilterInternal()方法
而在doFilterInternal()方法中会将过滤器链中的过滤器加载进来,进行逐个执行
当什么也没有配置的时候,账号和密码是由 Spring Security 定义生成的。而在实际项目中账号和密码都是从数据库中查询出来的。 所以要通过自定义逻辑控制认证逻辑。
如果需要自定义逻辑时,只需要实现 UserDetailsService 接口即可。
在 UserDetailsService 接口中只有一个方法loadUserByUsername()。
- 该方法的返回值是UserDetails接口的实现类对象,这个类是系统默认的用户 “主体” ,在Spring Security有一个UserDetails接口的实现类,类名就叫User。
- 该方法的参数username,表示用户名。此值是客户端表单传递过来的数据。默认情况下必须叫 username,否则无法接收。
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
所以,使用该接口的步骤则是:
PasswordEncoder创建类继承UsernamePasswordAuthenticationFilter过滤器,并且重写该类中的三个方法(doFilter方法,认证成功的方法,认证失败的方法)
创建类实现UserDetailsService,编写查询数据的过程,返回User对象(该对象是Spring Security提供的对象)
数据加密接口,用于返回User对象里面密码加密,而BCryptPasswordEncoder类是PasswordEncoder的实现类。
BCryptPasswordEncoder 是 Spring Security 官方推荐的密码解析器,平时多使用这个解析器。
BCryptPasswordEncoder 是对 bcrypt 强散列方法的具体实现。是基于 Hash 算法实现的单向加密。可以通过 strength 控制加密强度,默认 10.
具体使用方法可以我的主页搜索BCryptPasswordEncoder



