Spring Security+JWT在前后端分离项目中,实现认证授权的入门及理论讲解

spring security

spring security快速入门

在springboot项目中的pom.xml文件中引入spring-boot-starter-security依赖后,就可以针对访问资源进行保护,必须进行认证授权后,才能访问资源。
spring security自带一个登录页,如下图,用户名是:user,密码会在springboot启动日志中打印出来,示例【Using generated security password: 4876f76c-018e-4390-95f6-6e62bcb7be41

  • 登录地址:http://ip:port/context-path/login
  • 登出地址:http://ip:port/context-path/logout

默认情况下,在未登录的情况下,访问任何接口,都会跳转到登录地址。

只有熟悉快速入门安全中的Spring Security中的登录流程,才知道如何实现自己的登录流程
Spring Security+JWT在前后端分离项目中,实现认证授权的入门及理论讲解_第1张图片

<properties>
        <java.version>1.8java.version>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASEspring-boot.version>
properties>

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>${spring-boot.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
dependencyManagement>

<dependencies>
	  <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-starter-tomcatartifactId>
                exclusion>
                <exclusion>
                    <groupId>org.slf4jgroupId>
                    <artifactId>slf4j-log4j12artifactId>
                exclusion>
            exclusions>
        dependency>
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-undertowartifactId>
        dependency>
        
        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-securityartifactId>
        dependency>
        
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
dependencies>

登录校验流程

使用JWT生成Token进行接口鉴权实现方法
Spring Security+JWT在前后端分离项目中,实现认证授权的入门及理论讲解_第2张图片

Spring Security 流程

SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。下图包含了入门案例中的核心过滤器

  • UsernamePasswordAuthenticationFilter: 负责处理登录请求,主要根据用户名及密码进行认证工作
  • ExceptionTranslationFilter:处理过滤器链中抛出的任何AccessDeniedException和 AuthenticationException
  • FilterSecurityInterceptor: 负责权限校验的过滤器

过滤器链的默认实现是: org.springframework.security.web.DefaultSecurityFilterChain
Spring Security+JWT在前后端分离项目中,实现认证授权的入门及理论讲解_第3张图片
目前在整个过滤器链上,从DEBUG上看,共有15个过滤器,如下
Spring Security+JWT在前后端分离项目中,实现认证授权的入门及理论讲解_第4张图片

UsernamePasswordAuthenticationFilter 认证流程

此图来自:SpringSecurity框架教程-Spring Security+JWT实现项目级前端分离认证授权-B站最通俗易懂的Spring Security课程

  • Authentication接口: 表示当前访问系统的用户,封装了用户的相关信息
  • AuthenticationManager接口:定义了认证Authentication的方法
  • UserDetailsService接口:加载用户特定数据的核心接口,内部定义了一个根据用户名查询用户信息的方法
  • UserDetails接口:提供核心用户信息,通过UserDetailsService根据用户名获取处理的用户信息需要封装成UserDetails对象返回,然后将这些信息封装到Authentication对象中

注意:入门案例使用的是InMemoryUserDetailsManager,实际场景时,需要实现UserDetailsService这个接口,到数据库中查询用户信息。
Spring Security+JWT在前后端分离项目中,实现认证授权的入门及理论讲解_第5张图片

自定义认证流程实现

  • 用户登录系统的认证流程
    • 在Controller中自定义登录接口(实现功能如下图所示)
    • 自定义UserDetailsService类,实现到数据库中查询用户及权限信息
  • 用户校验的流程
    • 定义JWT认证过滤器,实现功能如下图所示
      Spring Security+JWT在前后端分离项目中,实现认证授权的入门及理论讲解_第6张图片
      Spring Security+JWT在前后端分离项目中,实现认证授权的入门及理论讲解_第7张图片

SecurityConfig

根据实际需要,实现自定义认证流程的登录接口、自定义UserDetailsService类及JWT认证过滤器后,
创建SecurityConfig类并做如下配置:

  • 关闭csrf
  • 解决跨域访问的问题
  • 添加JwtAuthenticationTokenFilter 过滤器
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/user/login").anonymous()
                .anyRequest().authenticated()
                .and()
                .cors();

        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        
    }
}
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry){
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("GET","POST","DELETE","PUT")
                .allowedHeaders("*")
                .maxAge(3600);
    }
}

token的刷新

这里简单说一下思路:

  • 在产生token时,在token中设置token的产生时间及过期时间,
  • 在访问受保护的资源时,都会检查token是否有效。
  • 如果token有效
    • 判断token是否需要过期刷新, token过期时间 - 系统当前时间 <= 10分钟
      • 如果成立,则针对token进行刷新
      • 否则,不刷新token
  • 否则跳转到登录页面

token的删除

  • 当用户退出时,则删除redis上的token
  • 当redis的token过期时,则redis自动删除过期的数据

你可能感兴趣的:(微服务架构,SpringSecurity,JWT,前后端分离,认证授权,Springboot)