SpringSecurity+JWT

一.简介

Spring Security 是 Spring家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。

  • 认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户
  • ​ 授权:经过认证后判断当前用户是否有权限进行某个操作

依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

引入依赖后我们在尝试去访问之前的接口就会自动跳转到一个SpringSecurity的默认登陆页面,默认用户名是user,密码会输出在控制台。

​ 必须登陆之后才能对接口进行访问。

 二.认证

1.登陆校验流程

2.SpringSecurity完整流程

​ SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器

UsernamePasswordAuthenticationFilter:负责处理我们在登陆页面填写了用户名密码后的登陆请求。入门案例的认证工作主要有它负责。
ExceptionTranslationFilter:处理过滤器链中抛出的任何AccessDeniedException和AuthenticationException。
FilterSecurityInterceptor:负责权限校验的过滤器。

3.认证流程详解

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

思路分析:

认证:

校验:

登录

​ ①自定义登录接口

​ 调用ProviderManager的方法进行认证 如果认证通过生成jwt

​ 把用户信息存入redis中

​ ②自定义UserDetailsService

​ 在这个实现类中去查询数据库

校验:

​ ①定义Jwt认证过滤器

​ 获取token

​ 解析token获取其中的userid

​ 从redis中获取用户信息

​ 存入SecurityContextHolder
 

创建一个类实现UserDetailsService接口,重写其中的方法。根据用户名从数据库中查询用户信息

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名查询用户信息
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUserName,username);
        User user = userMapper.selectOne(wrapper);
        //如果查询不到数据就通过抛出异常来给出提示
        if(Objects.isNull(user)){
            throw new RuntimeException("用户名或密码错误");
        }
        //TODO 根据用户查询权限信息 添加到LoginUser中
        
        //把对应的用户信息包括去权限信息封装成UserDetails对象返回 
        return new LoginUser(user);
    }
 

因为UserDetailsService方法的返回值是UserDetails类型,所以需要定义一个类,实现该接口,把用户信息封装在其中。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginUser implements UserDetails {

    private User user;


    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUserName();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

注意:如果要测试,需要往用户表中写入用户数据,并且如果你想让用户的密码是明文存储,需要在密码前加{noop}。

三.密码加密存储

默认使用的PasswordEncoder要求数据库中的密码格式为:{id}password 。它会根据id去判断密码的加密方式。但是我们一般不会采用这种方式。所以就需要替换PasswordEncoder。
​ 我们一般使用SpringSecurity为我们提供的BCryptPasswordEncoder。
我们只需要使用把BCryptPasswordEncoder对象注入Spring容器中,SpringSecurity就会使用该PasswordEncoder来进行密码校验。
​我们可以定义一个SpringSecurity的配置类,SpringSecurity要求这个配置类要继承WebSecurityConfigurerAdapter。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

// 密码加密方式

//创建BCryptPasswordEncoder注入容器
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

}

后面注入便可,private final PasswordEncoder passwordEncoder;

passwordEncoder.encode()  进行加密 ,返回加密的字符串

                               .matches()  密码校验  登录密码明文和 数据库密文进行比较

 5.登录接口
​ 接下来我们需要自定义登陆接口,然后让SpringSecurity对这个接口放行,让用户访问这个接口的时候不用登录也能访问。

​ 在接口中我们通过AuthenticationManager的authenticate方法来进行用户认证,所以需要在SecurityConfig中配置把AuthenticationManager注入容器。

​ 认证成功的话要生成一个jwt,放入响应中返回。并且为了让用户下回请求时能通过jwt识别出具体的是哪个用户,我们需要把用户信息存入redis,可以把用户id作为key。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/196655.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

扩散模型,快速入门和基于python实现的一个简单例子(复制可直接运行)

提示&#xff1a;内容丰富&#xff0c;收藏本文&#xff0c;以免忘记哦 文章目录 一、扩散模型二、一个简单的迭代式扩散模型的例子温度扩散模型python代码实现差分近似模拟拉普拉斯算子 三、扩散模型和深度学习进行结合简介用python和torch的代码实现 四、扩散模型与生成模型第…

JVM GC算法

一, 垃圾回收分类: 按线程数分&#xff0c;可以分为串行垃圾回收器和并行垃圾回收器。 按工作模式分&#xff0c;可以分为并发垃圾回收器和独占式垃圾回收器 按碎片处理方式分&#xff0c;可以分为压缩式垃圾回收器和非压缩式垃圾回收器按工作的内存区间分&#xff0c;又可分为…

C语言盐水的故事(ZZULIOJ1214:盐水的故事)

题目描述 挂盐水的时候&#xff0c;如果滴起来有规律&#xff0c;先是滴一滴&#xff0c;停一下&#xff1b;然后滴二滴&#xff0c;停一 下&#xff1b;再滴三滴&#xff0c;停一下...&#xff0c;现在有一个问题&#xff1a;这瓶盐水一共有VUL毫升&#xff0c;每一滴是D毫升&…

基于springBoot+mysql实现的竞赛管理系统

基于springBootmysql实现的竞赛管理系统&#xff0c;演示地址:系统登录 - 软件学院比赛管理系统 管理员账号&#xff1a;1&#xff0c;密码:1 包括比赛管理&#xff0c;队伍管理&#xff0c;教师管理&#xff0c;经费管理&#xff0c;学生管理&#xff0c;比赛结果&#xff0c;…

目前工资最高的几家外包公司汇总!(2023最新版)

最近&#xff0c;很多小伙伴问&#xff1a;只有外包的 offer 能去吗&#xff1f; 大环境不行&#xff0c;面试太少了&#xff0c;很多本科生想进外包都没机会。 非常时期&#xff0c;不需要在意那么多&#xff0c;外包作为过渡也是没问题的&#xff0c;很多外包其实比小公司还…

杂记 | 使用Docker安装并配置MongoDB以支持事务(单副本,并解决了证书文件错误的问题)

文章目录 00 安装前的准备01 创建Docker Compose文件02 设置证书文件03 启动MongoDB04 初始化副本集和创建用户05 验证安装 00 安装前的准备 在开始之前&#xff0c;确保已经安装了Docker&#xff0c;本文基于Docker Compose进行示范&#xff0c;没有装Docker Compose也可将其…

LeetCode算法题解(动态规划)|LeetCode198. 打家劫舍、LeetCode213. 打家劫舍 II、LeetCode337. 打家劫舍 III

一、LeetCode198. 打家劫舍 题目链接&#xff1a;198. 打家劫舍 题目描述&#xff1a; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的…

docker安装Sentinel zipkin

文章目录 引言I Sentinel安装1.1 运行容器1.2 DOCKERFILE 参考1.3 pom 依赖1.4 .yml配置(整合springboot)II 资源保护2.1 Feign整合Sentinel2.2 CommonExceptionAdvice:限流异常处理类III zipkin引言 消息服务和请求第三方服务可不配置Sentinel。 I Sentinel安装 Sentinel …

Fabric:搭建自定义网络

Hyperledger Fabric: V2.5.4 写在最前 从本篇博客开始&#xff0c;将陆续介绍使用Fabric搭建自定义网络及部署执行链码的过程。本篇主要介绍如何搭建网络。   由于前文在安装Fabric的时候&#xff0c;已经将目录fabric-samples/bin加入到了环境变量PATH中&#xff0c;所以正文…

Java 的第二十章:多线程

创建线程 继承Thread 类 Thread 类时 java.lang 包中的一个类&#xff0c;从类中实例化的对象代表线程&#xff0c;程序员启动一个新线程需要建立 Thread 实例。 Thread 对象需要一个任务来执行&#xff0c;任务是指线程在启动时执行的工作&#xff0c;start() 方法启动线程&am…

如何在自定义数据集上训练 YOLOv8 实例分割模型

在本文中&#xff0c;我们将介绍微调 YOLOv8-seg 预训练模型的过程&#xff0c;以提高其在特定目标类别上的准确性。Ikomia API简化了计算机视觉工作流的开发过程&#xff0c;允许轻松尝试不同的参数以达到最佳结果。 使用 Ikomia API 入门 通过 Ikomia API&#xff0c;我们只需…

C++ : 初始化列表 类对象作为类成员

传统方式初始化 C 提供了初始化列表语法&#xff0c;用来初始化属性 初始化列表 语法&#xff1a; 构造函数()&#xff1a;属性1(值1), 属性2&#xff08;值2&#xff09;... {} class Person { public://传统方式初始化 Person(int a, int b, int c) {m_A a;m_B b;m_C c…

生成工具集合

文章目录 前言一、SVG 波浪图片生成器二、背景图片生成器三、布局/形状分隔线四、Neumorphism五、动画按钮六、开发工具七、Interactions&#xff08;图片轮播&#xff09;八、CSS Gradient &#xff08;渐变属性&#xff09;九、获取波浪十、平滑阴影十一、CSS Clip-path Make…

图像重定向Image Retarget

1、什么是图像重定向&#xff1f; 图像重定向旨在调整图像的尺寸和比例&#xff0c;以适应不同的显示设备或布局要求。 它可以通过添加或删除像素来改变图像的宽度和高度&#xff0c;同时保持图像的内容和结构的相对比例。 这种技术可以通过保持图像的关键特征和结构来最大程度…

Java-多线程基本知识学习总结

多线程 前言一、线程的创建1、继承Thread类2、实现Runnable接口 二、线程的生命周期三、操作线程的方法1、线程的休眠2、线程的加入3、线程的礼让4、线程的优先级 四、线程同步End 前言 Java是支持多线程的编程语言&#xff0c;所谓多线程就是程序能够同时完成多种操作。 计算…

Linux中执行java命令报错:cannot execute binary file: Exec format error

网上很多文章 都是说操作系统和JDK&#xff0c;32位和64位不兼容问题 当你非常确定你的操作系统是64位&#xff0c;并且JDK也是64位的时候 或者非常确定你的操作系统是32位&#xff0c;并且JDK也是32位的时候 怎么办&#xff1f; 使用以下命令&#xff0c;查看你的操作系统…

IDEA插件推荐

今天给大家推荐一款IDEA插件&#xff1a;Apipost-Helper-2.0&#xff0c;支持三大功能&#xff1a;写完代码IDEA内一键生成API文档&#xff1b;写完代码IDEA内一键调试&#xff1b;生成API目录树&#xff0c;双击即可快速定位API定义的代码…非常好用&#xff01;而且完全免费&…

MySQL进阶-InnoDB引擎

✨作者&#xff1a;猫十二懿 ❤️‍&#x1f525;账号&#xff1a;CSDN 、掘金 、语雀 、Github &#x1f389;公众号&#xff1a;猫十二懿 一、InnoDB 逻辑存储引擎 InnoDB的逻辑存储结构如下图所示&#xff1a; 大小关系&#xff1a;表空间&#xff08;Tablespace&#xff0…

消息队列MQ

文章目录 同步通讯和异步通讯什么是MQ?一.RabbitMQ概述二.SpringAMQP1.Work Queue 工作队列2.发布订阅-Fanout Exchange3.发布订阅-DirectExchange4.发布订阅-TopicExchange 3.消息转换器 同步通讯和异步通讯 其实在之前的JAVASE中就已经在线程一章中接触过了同步和异步的概念…

实战:登录接口测试用例举例

以下是一些可能的登录接口测试用例&#xff08;使用Python编写的&#xff09;&#xff1a; 1. 测试正常情况下的登录接口&#xff1a; # 请求URL url "https://example.com/api/login" # 请求参数 username "testuser" password "testpassword&q…