springBoot+springSecurity基本认证流程

springBoot+springSecurity认证流程

整合springSecurity

对应springboot版本,直接加依赖,这样版本不会错

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

比如我这里是2.6.4的版本。对应的springSecurity版本是5.6.x

在这里插入图片描述

没找到springSecurity对应springboot依赖对应表

但springboot2.x基本对应security的5.x版本

3.x对应6.x版本

最基本的概念:

  • 认证和授权
    • 认证(Authentication):用户输入账户密码,系统让其登录到系统里
    • 授权(authorities):用户的权限不同,他们能在系统做的事情都不同

springSecurity如何实现认证

UsernamePasswordAuthenticationToken可以允许你传入username和password参数

关键代码

UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());

然后调用UserDetailsService的loadUserByUsername方法根据username查出数据库中的这个用户

 @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //查询用户信息
        User user = userMapper.findByColumnAndValue("user_name", username);
        if(user==null){
            throw new UsernameNotFoundException("用户名或密码错误");
        }
        //查询用户权限
        List<String> perms = menuMapper.selectPermsByUserId(user.getId());
        return new LoginUser(user,perms);
    }

然后可以调用authenticationManager.authenticate方法对用户输入的账号密码进行验证,密码会经过passwordEncoder去加密,然后和数据库中该用户的账号密码比对。

//加密器 bean
@Bean
    public PasswordEncoder PasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
//验证逻辑
Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);

如果通过,返回一个Authentication对象,封装了该用户的信息。像这样:

**外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传**

这时需要将信息保存到Security上下文

像这样:

SecurityContextHolder.getContext().setAuthentication(authenticate);

这样,后面的代码就可以通过SecurityContextHolder.getContext()来获取当前用户了。

在这里插入图片描述

如果失败,springSecurity会抛出一个异常:AuthenticationException

框架有默认异常处理器,但一般你可以自定义异常处理器,并把错误信息和业务整合。像这样:

@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        ResponseResult<Object> noAuthentication = ResponseResult.noAuthentication("认证失败");
        String json = JSON.toJSONString(noAuthentication);
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Cache-Control","no-cache");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        response.getWriter().println(json);
        response.getWriter().flush();
    }
}

其他接口如何校验用户是否登录

需要一个检查登录过滤器,这个过滤器要通过检查token,并解析出用户信息,保存到Security上下文

@Component
public class CheckLoginFilter extends OncePerRequestFilter {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisCache redisCache;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 如果请求路径是登录接口,直接放行
        String requestURI = request.getRequestURI();
        if ("/user/login".equals(requestURI)) {
            filterChain.doFilter(request, response);
            return;
        }

        //获取token
        String token = request.getHeader("token");
        if(token==null){
            //springSecurity有一个过滤器会自动检查Context有没有认证
            throw new RuntimeException("token为空");
        }
        //解析token,获取userId
        Claims claims = JwtUtils.parserClaimsFromToken(token);
        if(claims==null){
            throw new RuntimeException("token非法");
        }
        //从redis数据库里取
        Long userId = claims.get("userId", Long.class);
        String redisKey="login:"+userId;
        LoginUser loginUser = (LoginUser) redisCache.getCacheObject(redisKey);
        if(loginUser==null){
            throw new RuntimeException("没有登录:redis没有登录key");
        }
        //todo 从数据库查该用户的权限,先写死
        //将用户信息存入Authentication
        //权限存入,全局设置为该请求已经认证过
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        //checkLogin完成,放行
        filterChain.doFilter(request,response);

    }
}

基本流程图(转自https://www.bilibili.com/video/BV1mm4y1X7Hc?p=39&vd_source=a312f003d7c3e57dfd813b31f9cd4a8e)
在这里插入图片描述

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

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

相关文章

vue实战----网易云音乐案例

1 . 能够掌握Vant组件库使用2 . 熟练查阅Vant组件库文档3 . 能够完成网易云音乐案例 案例-网易云音乐 1.本地接口 目标&#xff1a;下载网易云音乐node接口项目, 在本地启动, 为我们vue项目提供数据支持 2.本地接口启动 目标&#xff1a;启动本地node服务_拿到数据 文档: …

Golang创建文件夹

方法 package zdpgo_fileimport ("os" )// AddDir 创建文件夹 func AddDir(dir string) error {if !IsExist(dir) {return os.MkdirAll(dir, os.ModePerm)}return nil }测试 package zdpgo_fileimport "testing"func TestAddDir(t *testing.T) {data : […

二叉树(详解)

在了解二叉树之前呢我们先来了解一下树形结构&#xff0c;因为二叉树就是树形结构的一种特殊情况&#xff0c;它有这非常好的性质&#xff0c;是很常用的一种结构。 目录 一.什么是树形结构&#xff1f; 二.树形结构常见的名词 三.树的存储 四.二叉树 1.二叉树的概念 2.…

学习记录16-反电动势

一、反电动势公式 在负载下反电势和端电压的关系式为&#xff1a;&#x1d448;&#x1d43c;&#x1d445;&#x1d43f;*&#xff08;&#x1d451;&#x1d456; / &#x1d451;&#x1d461;&#xff09;&#x1d438; E为线圈电动势、 &#x1d713; 为磁链、f为频率、N…

网络协议——Modbus-TCP

目录 1、简介 2、Modbus-TCP与Modbus-RTU的区别 3、消息格式 4、功能码01H 5、功能码02H 6、功能码03H 7、功能码04H 8、功能码05H 9、功能码06H 10、功能码0FH 11、功能码10H 1、简介 Modbus-TCP&#xff08;Modbus Transmission Control Protocol&#xff09;是一…

基于Django的美团药品数据分析与可视化系统,有多用户功能,可增删改查数据

背景 随着电子商务和健康产业的迅速发展&#xff0c;药品行业数据的分析和可视化变得愈发重要。基于Django的美团药品数据分析与可视化系统的研究背景凸显了对药品数据的深入挖掘和分析的需求。该系统不仅具备多用户功能&#xff0c;允许不同角色的用户进行数据管理和分析&…

2024最新流媒体在线音乐系统网站源码| 音乐社区 | 多语言 | 开心版

简介&#xff1a; 2024最新流媒体在线音乐系统网站源码| 音乐社区 | 多语言 | 开心版 下载地址 https://www.kuaiyuanya.com/product/article/index/id/33.html 图片&#xff1a;

【无重复字符的最长子串】python,滑动窗口+哈希表

滑动窗口哈希表 哈希表 seen 统计&#xff1a; 指针 j遍历字符 s&#xff0c;哈希表统计字符 s[j]最后一次出现的索引 。 更新左指针 i &#xff1a; 根据上轮左指针 i 和 seen[s[j]]&#xff0c;每轮更新左边界 i &#xff0c;保证区间 [i1,j] 内无重复字符且最大。 更新结…

高铁VR虚拟全景展示提升企业实力和形象

步入VR的神奇世界&#xff0c;感受前所未有的汽车展示体验。VR虚拟现实技术以其独特的沉浸式模拟&#xff0c;让你仿佛置身于真实展厅之中&#xff0c;尽情探索汽车的每一处细节。 一、定制化展示&#xff0c;随心所欲 VR汽车虚拟展厅打破空间束缚&#xff0c;让汽车制造商能够…

区块链开发:区块链软件开发包装相关解析

区块链开发是指设计、构建和维护基于区块链技术的应用程序或系统的过程。区块链是一种分布式账本技术&#xff0c;它通过去中心化的方式记录和验证数据&#xff0c;确保数据的透明性、不可篡改性和安全性。区块链开发者使用各种编程语言和框架来创建这些应用程序。 在加密货币领…

C++ sort排序的总和应用题

第1题 sort排序1 时限&#xff1a;1s 空间&#xff1a;256m 输入n个数&#xff0c;将这n个数从小到大排序&#xff0c;输出。 输入格式 第1行&#xff0c;一个正整数n&#xff08;n<100&#xff09; 第2行&#xff0c;n个正整数&#xff0c;小于100 输出格式 n个整…

Windows安装mingw32/w64

1.下载 MinGW-w64 WinLibs - GCCMinGW-w64 compiler for Windows Releases niXman/mingw-builds-binaries (github.com) MinGW-w64、UCRT 和 MSVCRT 是 Windows 平台上常用的 C/C 运行库&#xff0c;它们有以下不同点&#xff1a; MinGW-w64&#xff1a;是一个基于 GCC 的…

【Hive SQL 每日一题】分析电商平台的用户行为和订单数据

需求描述 假设你是一位数据分析师&#xff0c;负责分析某电商平台的用户行为和订单数据&#xff0c;平台上有多个用户&#xff0c;用户可以在不同的日期下单&#xff0c;每个订单包含多个商品。请你完成相关业务分析&#xff0c;帮助平台优化运营策略和用户体验。 数据准备 …

NDIS小端口驱动(五)

在需要的时候&#xff0c;我们也许需要NDIS微型端口程序信息&#xff0c;下面会从多个方面来讨论如何查询NDIS微型端口驱动。 查询无连接微型端口驱动程序 若要查询无连接微型端口驱动程序维护的 OID&#xff0c;绑定协议调用 NdisOidRequest 并传递 一个NDIS_OID_REQUEST 结…

【SQL每日一练】查询“OCCUPATIONS”中的“Occupation”列并按Doctor、Professor、Singer、Actor列输出

文章目录 题目一、分析二、题解1.SqlServer2.MySQL3.Oracle 总结 题目 查询“OCCUPATIONS”中的“Occupation”列&#xff0c;使每个姓名按字母顺序排序&#xff0c;并显示在其相应的“职业》下方。输出列标题应分别为Doctor、Professor、Singer和Actor。 注意&#xff1a;当不…

【ChatGPT】 Microsoft Edge 浏览器扩展使用 GPT

【ChatGPT】添加 Microsoft Edge 浏览器插件免费使用 GPT 文章目录 准备工作添加扩展注意事项 使用 ChatGPT 可以更高效的搜索到想要的内容&#xff0c;有效节约在搜索引擎中排查正确信息的时间。 准备工作 准备一台可上网的电脑电脑上安装有 Windows 自带的 Microsoft Edge …

【Makefile】Makefile 编译 Keil 工程(Linux 环境)

本文使用的开发板为 stm32f103C8T6&#xff0c;使用的驱动库为stm32标准库。 目录 一、软件下载 1、stm32 标准库 2、arm-none-eabi 工具链 3、烧录器 二、Keil 工程改造 1、Keil 工程 2、基本 Makefile 工程 3、添加启动文件 4、添加链接脚本 5、去掉 core_cm3.c 三…

App Inventor 2 如何接入ChatGPT:国内访问OpenAI的最佳方式

如何接入OpenAI 由于国内无法访问OpenAI&#xff0c;KX上网可选大陆及香港&#xff08;被屏蔽&#xff09;以外才行。因此对于大多数人来说&#xff0c;想体验或使用ChatGPT就不太便利&#xff0c;不过App Inventor 2 为我们提供了相对便利的一种方式&#xff0c;即“试验性质…

基于STM32F407的项目迁移到STM32F427

提示&#xff1a;此文档迁移教程使用的是IAR&#xff0c;有关代码的修改使用的是Vscode,基于STM32F407的项目迁移到STM32F427 基于STM32F407的项目迁移到STM32F427 前言一、硬件区别1.1.区别&#xff1a;1.2.需要注意以下硬件区别&#xff1a; 二、引脚配置三、STM32F4273.1.晶…

安卓高级控件(下拉框、列表类视图、翻页类视图、碎片Fragment)

下拉框 此小节介绍下拉框的用法以及适配器的基本概念&#xff0c;结合对下拉框Spinner的使用说明分别阐述数组适配器ArrayAdapter、简单适配器SimpleAdapter的具体用法与展示效果。 下拉框控件Spinner Spinner是下拉框控件&#xff0c;它用于从一串列表中选择某项&#xff0…