前言
2021SC@SDUSC
概述
在之前的所有分析中,我们分析了项目的配置和架构情况,并且根据后端的MVC架构,在不同的层级,对spring boot框架本身以及注解的使用方法和内部原理进行了着重分析,希望能加深对spring boot框架机制的理解情况。
在后面的分析里,我们将把分析的重点放在项目所使用的其他技术上,比如jwt,spring security,rabbitmq,nginx等等,重点讲解其内部原理,附带项目配置和使用方法。
在本次的博客里,我们将重点先放在项目的身份校验与权限控制上,技术上使用了jwt+spring security+filter来实现。
基本配置
可参考:
Spring Security基本配置 - 仅此而已-远方 - 博客园
以及我项目组成员的具体介绍:
Spring Security+JWT实现身份认证与权限控制_alphahao的博客-CSDN博客
后者有在本项目的详细配置,不再赘述。
原理分析
身份校验
Spring Security的登录验证流程核心是过滤器链(Filter Chain)。
当一个请求到达时按照过滤器链的顺序依次进行处理,通过所有过滤器链的验证的请求才能访问接口。
同时,在验证的同时进行授权,方便之后的权限管理。
(图源alphahao)
Spring Security的封装程度较高,我们使用时只需要调用其实现的方法就可以实现相关功能。
SpringSecurity提供了多种登录认证的方式,由多种Filter过滤器来实现,比如:
- BasicAuthenticationFilter实现的是HttpBasic模式的登录认证
- UsernamePasswordAuthenticationFilter实现用户名密码的登录认证
- RememberMeAuthenticationFilter实现登录认证的“记住我”的功能
- SmsCodeAuthenticationFilter实现短信验证码登录认证
- SocialAuthenticationFilter实现社交媒体方式登录认证的处理
- Oauth2AuthenticationProcessingFilter和Oauth2ClientAuthenticationProcessingFilter实现Oauth2的鉴权方式
以用户名密码的登录认证为例的流程如下:(图源alphahao)
security config源码:
spring security的全局配置都在这里,在此方法中添加filter来控制身份校验的流程。
package cn.sdu.sdupta.config;
import cn.sdu.sdupta.filter.JwtAuthenticationFilter;
import cn.sdu.sdupta.filter.OptionsRequestFilter;
import cn.sdu.sdupta.handler.UsernameLoginSuccessHandler;
import cn.sdu.sdupta.handler.JwtRefreshSuccessHandler;
import cn.sdu.sdupta.service.JwtUserService;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
import java.util.Collections;
@EnableWebSecurity(debug = false)
@EnableGlobalMethodSecurity(prePostEnabled = true)
class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//授权
http.authorizeRequests()
.antMatchers("/user/login", "/user/admin/login", &#