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。

加密:createJWT:三种:(id,加密的数据,过期时间)或者就传一个加密数据

token中存放的数据(json格式) :把对象转json格式字符串,然后加密

解密:parseJWT(jwt字符串).var

claims.getSubject().var

@RestController
public class LoginController {

    @Autowired
    private LoginServcie loginServcie;

    @PostMapping("/user/login")
    public ResponseResult login(@RequestBody User user){
        return loginServcie.login(user);
    }
}


 

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

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

相关文章

虚幻学习笔记3—UI跟随弹窗

一、前言 本文使用的虚幻引擎5.3.2&#xff0c;继点击场景3D物体的两种处理方式的基础完成对3D物体的点击触发后&#xff0c;我们需要制作一个可以弹窗显示该物体信息的UI面板&#xff0c;同时保证弹窗可以跟随物体。另外还讲了一种UI上的悬浮提示跟随弹窗。 二、实现 2.1、创…

Pytorch:torch.utils.data.DataLoader()

如果读者正在从事深度学习的项目&#xff0c;通常大部分时间都花在了处理数据上&#xff0c;而不是神经网络上。因为数据就像是网络的燃料&#xff1a;它越合适&#xff0c;结果就越快、越准确&#xff01;神经网络表现不佳的主要原因之一可能是由于数据不佳或理解不足。因此&a…

ArcGIS Pro、Python、USLE、INVEST模型等多技术融合的生态系统服务构建生态安全格局

近年来&#xff0c;由于社会经济的快速发展和人口增长&#xff0c;社会活动对环境的压力不断增大&#xff0c;人地矛盾加剧。虽然全球各国在生态环境的建设和保护上已取得不少成果&#xff0c;但还是未从根本上转变生态环境的恶化趋势&#xff1b;生态破坏、环境退化、生物多样…

rss服务搭建记录

layout: post title: RSS subtitle: vps搭建RSS服务 date: 2023-11-27 author: Sprint#51264 header-img: img/post-bg-universe.jpg catalog: true tags: - 折腾 文章目录 引言RSShub-dockerRSS-radarFreshrssFluent reader获取fever api配置Fluent Reader同步 结语 引言 一个…

【代码】数据驱动的多离散场景电热综合能源系统分布鲁棒优化算法matlab/yalmip+cplex/gurobi

程序名称&#xff1a;数据驱动的多离散场景电热综合能源系统分布鲁棒优化算法 实现平台&#xff1a;matlab-yalmip-cplex/gurobi 代码简介&#xff1a;数据驱动的分布鲁棒优化算法。考虑四个离散场景&#xff0c;模型采用列与约束生成(CCG)算法进行迭代求解&#xff0c;场景分…

C#键盘钩子(Hook)拦截器的使用

引言 键盘钩子(Hook)是一种机制&#xff0c;允许程序捕获和处理操作系统中的键盘输入。在C#中&#xff0c;我们可以使用键盘钩子来创建一个拦截器&#xff0c;用于拦截特定的键盘事件并执行自定义操作。本文将介绍如何使用C#开发一个键盘钩子拦截器&#xff0c;并给出一些示例代…

苹果手机如何格式化?五个步骤快速掌握!

如果手机出现异常情况&#xff0c;例如运行缓慢、频繁崩溃&#xff0c;又或者想将手机出售、转让给他人&#xff0c;那么将手机格式化可以有助于解决问题。苹果手机如何格式化&#xff1f;本文将为您介绍解决方法&#xff0c;只需要五个步骤就能搞定&#xff0c;帮助您快速掌握…

一维数组,逆序存放并输出【样例输入】20 30 10 50 40 90 80 70【样例输出】70 80 90 40 50 10 30 20

一维数组&#xff0c;逆序存放并输出 【样例输入】 20 30 10 50 40 90 80 70 【样例输出】 70 80 90 40 50 10 30 20 以下是使用C语言编写的将一维数组逆序存放并输出的示例代码&#xff1a; #include <stdio.h>void reverseArray(int arr[], int size) {int start…

Xilinx Zynq-7000系列FPGA多路视频处理:图像缩放+视频拼接显示,提供工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐FPGA图像处理方案FPGA图像缩放方案FPGA视频拼接叠加融合方案推荐 3、设计思路详解HLS 图像缩放介绍Video Mixer介绍 4、vivado工程介绍PL 端 FPGA 逻辑设计PS 端 SDK 软件设计 5、工程移植说明vivado版本不一致处理FPGA型号不一致处理其他…

全网日志智能聚合及问题根因分析

1 日志关联分析的挑战 随着各行各业数字化转型的不断深入&#xff0c;网络承载了人们日常生活所需的政务、金融、娱乐等多方面的业务系统&#xff0c;已经成为影响社会稳定运行、关系国计民生的重要基础设施资源。哪怕网络发生及其微小的故障&#xff0c;也可能带来难以估量的…

【预测爆款不用愁,有服饰RFID小助手】

时尚服饰行业库存成本高&#xff0c;数据不精准&#xff0c;爆款服饰一直抓不住&#xff0c;增加库存滞销风险难脱逃&#xff0c;给服饰零售企业带来极大困扰。 帮您提前预测爆款服饰小塔服饰RFID系统 小塔RFID系统作为服饰新零售小助手&#xff0c;通过RFID系统与硬件结合&a…

在Springboot中操作Redis——五大数据类型

在Java中操作Redis Redis的Java客户端 前面我们讲解了Redis的常用命令&#xff0c;这些命令是我们操作Redis的基础&#xff0c;那么我们在java程序中应该如何操作Redis呢&#xff1f;这就需要使用Redis的Java客户端&#xff0c;就如同我们使用JDBC操作MySQL数据库一样。 Red…

重温 re:Invent,分享十年成长:我和 re:Invent的故事

文章目录 前言背景我和re:Invent的交际历届峰会主题2012 突破技术垄断2013 革新数据服务2014 更好用的云服务2015 打通最后一-公里2016 迈向云上数据湖时代2017 重构云计算基础2018 云能力的再进化2019 赋能企业云架构服务2020 推动行业数据库服务的演进2021 无可比拟的云架构2…

pdf文件编辑,[增删改查]

pdf文件是投标文件中必不可少的格式&#xff0c;传统的方式先编辑word格式&#xff0c;最后生成pdf&#xff0c;但是有时候需要直接编辑pdf文件&#xff0c;编辑pdf的工具无疑 “adobe acrobat dc”是最好用的之一了 1.把图片文件添加到pdf指定位置&#xff0c;例如把一张图片添…

API网关

API网关的作用 下图显示了详细信息。 步骤 1 - 客户端向 API 网关发送 HTTP 请求。 步骤 2 - API 网关解析并验证 HTTP 请求中的属性。 步骤 3 - API 网关执行允许列表/拒绝列表检查。 步骤 4 - API 网关与身份提供商对话以进行身份​​验证和授权。 步骤 5 - 将速率限制规…

亚马逊云科技Aurora MySQL在复制性能提升上的不断优化和尝试

前言 Amazon Aurora是亚马逊云科技自研的云原生关系数据库&#xff0c;它在提供和开源数据库MySQL、PostgreSQL的完好兼容性同时&#xff0c;也能够提供和商业数据库媲美的性能和可用性。 Aurora的性能提升不仅包含应用读写吞吐量的提升&#xff0c;也包含复制延迟的降低。一个…

echart 柱状图-bar

业务场景一 效果 业务组件调用代码 <template> <barCom :domId"1" :title"barComProps.title" :xAxisData"barComProps.xAxisData" :yAxisProps"barComProps.yAxisProps" :seriseData"barComProps.serise…

在数据库中进行表内容的修改(MYSQL)

根据表中内容&#xff0c;用命令语句创建数据库&#xff0c;表格&#xff0c;以及插入&#xff0c;修改&#xff0c;删除表格中的内容。 创建数据库&#xff1a;zrzy mysql> create database zrzy; 引用zrzy数据库&#xff1a; mysql> use zrzy; 创建student_info表&…

【EasyExcel实践】导出多个sheet到多个excel文件,并压缩到一个zip文件

文章目录 前言正文一、项目依赖二、封装表格实体和Sheet实体2.1 表格实体2.2 Sheet实体 三、核心实现3.1 核心实现之导出为输出流3.2 web导出3.3 导出为字节数组 四、调试4.1 构建调试用的实体类4.2 控制器调用4.3 测试结果 五、注册大数转换器&#xff0c;长度大于15时&#x…

XML Schema中的attributeFormDefault

XML Schema中的attributeFormDefault属性&#xff0c;用以指定元素的属性默认是否必须带有命名空间前缀。 attributeFormDefault属性可以取值qualified或unqualified&#xff0c;默认值是unqualified。 当取值为qualified时&#xff0c;表示属性必须用命名空间作为前缀&#x…