springsecurity认证流程

news2024/11/25 10:58:27

Authentication


AuthenticationManager : 认证管理器

实现类:

  • ProviderManager

AuthenticationProvider :
实现类:

  • DaoAuthenticationProvider
  • RememberMeAuthenticationProvider

方法:

  • authenticate()
  • supports() : 判断当前AuthenticationProvider是否支持对应的身份类型

AuthenticationProvider

AbstractUserDetailsAuthenticationProvider :
在这里插入图片描述
具体的认证逻辑在AbstractUserDetailsAuthenticationProvider#authenticate 方法中
在这里插入图片描述
在这里插入图片描述

DaoAuthenticationProvider 继承自 AbstractUderDetailsAuthenticationProvider
在这里插入图片描述
在这里插入图片描述
总结:

AbstractUserDetailsAuthenticationProvider#authenticate :

  1. 先从缓存里面获取
  2. 获取不到 retrieveUser 找回user,,也就是从UserDetailsService#loadUserByUsername中找UserDetails
  3. 找到之后对 UserDetails进行判断
    preAuthenticationChecks : 检查用户状态
    additionalAuthenticationChecks : 密码的校验
    postAuthenticationChecks : 密码是否过期
  4. 创建一个认证后的UsernamePasswordAuthenticationToken

ProviderManager

在这里插入图片描述
ProviderManager本身可以有多个,,也就是不同的认证方式,,多个ProviderManager可以共用一个parent,,
共有的认证方式可以在parent中处理
在这里插入图片描述
ProviderManager#authenticate 方法,,会挨个遍历AuthenticationProvider,,调用AuthenticationProvider#authenticate,

AbstractAuthenticationProcessingFilter

在这里插入图片描述

如果使用用户名密码登录: 实现类: UsernamePasswordAuthenticationFilter
过滤器会构造出一个 Authentication 对象,则是UsernamePasswordAuthenticationToken,然后在ProviderManager中进行认证,,认证成功进入成功回调

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

配置多个数据源

@Configuration
public class SecurityConfig01  extends WebSecurityConfigurerAdapter {
    @Bean
    UserDetailsService us1(){
        /**
         * AuthenticationProvider#retrieveUser  获取user 会调用 UserDetailsService#loadUserByUsername
         */
        // 配置UserDetailsService  返回UserDetails
        InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager(User.builder().username("cc").password("{noop}123").roles("admin").build());
        return userDetailsService;
    }

    @Bean
    UserDetailsService us2(){
        InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager(User.builder().username("hh").password("{noop}123").roles("user").build());
        return userDetailsService;
    }
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        DaoAuthenticationProvider provider01 = new DaoAuthenticationProvider();
        provider01.setUserDetailsService(us1());

       DaoAuthenticationProvider provider02 = new DaoAuthenticationProvider();
       provider02.setUserDetailsService(us2());

       ProviderManager providerManager = new ProviderManager(provider01,provider02);

       return providerManager;
    }

}

加入登录验证码

  • 自定义认证逻辑 添加验证码

就是添加自己的AuthenticationProvider,,,在原有的 DaoAuthenticationProvider基础上修改,,添加验证码校验:

  1. 生成验证码,并存入session中
    导包:
 <dependency>
            <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
            <version>2.3.2</version>
 </dependency>
@Configuration
public class CaptchaConfig {

    @Bean
    public Producer kaptcha(){
        /**
         * DefaultKaptcha  implements  Producer
         * */
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty("kaptcha.image.width","150");
        properties.setProperty("kaptcha.image.height","50");
        properties.setProperty("kaptcha.textproducer.char.string","0123456789");
        properties.setProperty("kaptcha.textproducer.char.length","4");

        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);

        return defaultKaptcha;
    }

}

生成图片的接口:

  @Autowired
    Producer producer;
    
    @GetMapping("/verifyCode")
    public void verifyCode(HttpServletResponse resp, HttpSession session) throws IOException {
        String text = producer.createText();
        System.out.println("text = " + text);
        BufferedImage image = producer.createImage(text);
        session.setAttribute("captcha",text);
        // 返回图片,要写contentType
        resp.setContentType("image/jpeg");
        try(ServletOutputStream out = resp.getOutputStream()){
            ImageIO.write(image,"jpg",out);
        }
    }
  1. 自定义AuthencationProvider ,比较验证码
public class CaptchaAuthenticationProvider extends DaoAuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = requestAttributes.getRequest();

        String captcha = req.getParameter("captcha");
        String sessionCaptcha = (String) req.getSession().getAttribute("captcha");

        if (captcha != null && captcha.equals(sessionCaptcha)){
            return super.authenticate(authentication);
        }
        throw new AuthenticationServiceException("验证码错误");
    }
}
  1. 在配置文件中引入自己的AuthenticationProvider,放开验证码接口
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    UserDetailsService us1(){
        return new InMemoryUserDetailsManager(User.withUsername("cc").password("{noop}123").roles("admin").build());
    }

    @Bean
    AuthenticationProvider captchaAuthenticationProvider(){
        CaptchaAuthenticationProvider provider = new CaptchaAuthenticationProvider();
        provider.setUserDetailsService(us1());
        return provider;
    }


    @Override
    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        ProviderManager providerManager = new ProviderManager(captchaAuthenticationProvider());
        return providerManager;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/verifyCode").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/doLogin")
                .permitAll()
                .and()
                .csrf().disable();
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

dubbo学习笔记2(小d课堂)

dubbo核心架构及流程 企业中dubbo常见的多种开发方式 详解dubbo服务注册中心 Dubbo整合zookeeper 我们主要是改这部分&#xff1a; 然后我们启动本地的zookeeper&#xff0c;再去启动它&#xff1a; 会报错&#xff0c;这是说我们缺少响应的jar包&#xff1a; 就可以了。 我们提…

〖Python 数据库开发实战 - Python与Redis交互篇⑨〗- 利用 redis-py 实现模拟商品秒杀活动案例

文章目录 ❤️‍&#x1f525; 为什么要引入线程池技术 ❤️‍&#x1f525; 通过案例加深线程池技术原理的理解 ❤️‍&#x1f525; 实现多线程模拟商品秒杀案例 - 思路 ❤️‍&#x1f525; 实现多线程模拟商品秒杀案例 - 代码 今天的这一章节我们将来实现 “模拟商品秒杀活…

ES6 课程概述②

文章目录更好的 Unicode 支持更多的字符串 API3-3. [扩展]正则中的粘连标记模板字符串3-5. [扩展]模板字符串标记4-1. 参数默认值使用[扩展]对 arguments 的影响[扩展]留意暂时性死区4-2. 剩余参数4-3. 展开运算符对数组展开 ES6对对象展开 ES7函数柯里化4-5. 明确函数的双重用…

【菜菜的CV进阶之路 - 深度学习环境搭建】配置Ubuntu深度学习环境

六、配置Ubuntu深度学习环境 1、安装Google chrome 使用wget下载最新的Google Chrome .deb软件包&#xff1a; wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb更多地址可参考&#xff1a;在Deepin v20系统中下载和安装谷歌Chrome最新版de…

Vue学习笔记(一)

Vue学习笔记1. 什么是Vue2. 安装Vue2.1 使用独立版本2.2 使用CDN方式2.3 使用NPM方式3.Vue语法3.1 el挂载点3.2 data数据对象3.3 V-text 设置标签内的内容3.4 V-html3.5 V-on3.6 计数器3.7 v-show3.8 V-if3.9 v-bind3.10 v-for3.11 V-model4.class与style绑定5.表单输入绑定5.1…

【vue2】基础概念 01 (vue框架介绍、el、data、插值表达式)

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;vue框架介绍、结构元素详解&#xff08;el、data、插值表达式&#xff09; 目录&#xf…

《我是个怪圈》读书笔记

文章目录书籍信息论灵魂及其尺寸摇曳在恐惧与梦想之间的那只电灯泡&#xff08;取自拉塞尔埃德森的诗&#xff09;模式的因果潜力关于自我与符号副现象模式与可证性哥德尔的典型怪圈奇迹般步调划一的同步在公式与大整数之间翻转很大的整数与公式步调一致的移动质雅数怪圈论向下…

vue实现文件预览功能

目录 一、使用插件预览 1.前端实现在线预览文档 通过联机查看 Office 文档 打开新窗口预览文件 当前页面预览文件 注意事项 在创建好url之后&#xff0c;可能会出现无法打开文档的情况&#xff0c;这时候就需要对照官网的解释来查找问题了&#xff0c;官方文档的解释如下…

k线图入门精讲

K线图是贵金属技术分析的基础手段&#xff0c;刚入门的投资者应认真学习和理解k线的基础知识&#xff0c;因为有了认识才能分析。然而&#xff0c;多数上班族精力有限&#xff0c;无法耗费大量精力学习&#xff0c;今天小编就为准备了K线入门的“精读班”。 一、K线的作用 K线图…

【node.js】fs\path\http模块的使用 02

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;Node.js的fs\path\http模块的使用&#xff0c;模块化开发概念 目录 一、node.js概念与作…

Java程序员你自己的菜鸟气质霸气侧漏了吗?

对于刚入行的程序员来说&#xff0c;面对各种各样的陌生配置环境和代码库&#xff0c;难免会手忙脚乱&#xff0c;尽显菜鸟本色。 但从啥都需要教的菜鸟到啥都懂的大神程序员&#xff0c;并不简单&#xff0c;这需要牺牲一根又一根宝贵的头发&#xff0c;直到它们肉眼可数。 …

线上服务器CPU占用过高?7步带你搞定

一. 前言在Java开发岗位的面试中&#xff0c;时不时会出现一些运维类的题目&#xff0c;其实这也反映了后端面试的一种趋势。现在企业对后端开发的要求越来越全面&#xff0c;不仅要求我们会写代码&#xff0c;还要我们能够进行部署和运维。今天壹哥就结合一个真实的项目案例&a…

【Linux】Linux权限

权限的概念 限制人的&#xff0c;访问的对象天然可能没有这种“属性”权限&#xff1a;一件事情是否允许被谁“做”。 权限 人 事物属性 Linux上的用户分类 root&#xff0c;超级管理员&#xff0c;几乎可以干任何事情&#xff08;1个&#xff09;普通用户&#xff08;多个&a…

雷电飞机大战游戏|基于Java开发实现雷电飞机大战游戏

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

【前端】Vue项目:旅游App-(8)city:标签页Tabs动态数据:网络请求axios与request、数据管理store与pinia、各种封装

文章目录目标过程与代码安装相关库封装网络请求相关代码网络请求数据网络请求数据操作封装pinia管理数据并封装tab栏改为动态数据效果本篇总结总代码修改或新建的文件serviceindexmodules的cityrequest的configrequest的indexstoremodules的citymodules的loadingcity.vue参考目…

录屏没有声音怎么办?录屏怎么录声音

相信部分朋友在录制视频时&#xff0c;有出现录制视频没有声音&#xff0c;导致该段视频没有声音而无法播放。录屏怎么录声音&#xff1f;可以使用支持录制声音的专业的电脑录屏软件。今天小编就在这给大家分享在录制视频同时&#xff0c;将声音也录制进去的操作步骤。一、录屏…

【Linux】主函数的三个形参

主函数的形参有三个&#xff1a;argc参数个数&#xff0c;argv参数内容&#xff0c;envp环境变量。其中argc是整型&#xff0c;argv和envp是指针数组&#xff08;存的字符串&#xff09; argv源于我们自己在使用执行命令时传的内容&#xff0c;envp源于程序的父进程&#xff08…

力扣sql入门篇(十)

力扣sql入门篇(十) 1 查找重复的电子邮箱 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 SELECT Email FROM Person GROUP BY Email HAVING count(id)>21.3 运行截图 2 合作过至少三次的演员和导演 2.1 题目内容 2.1.1 基本题目信息 2.1.2 示例…

Java并发编程(六)ExecutorService

ExecutorService invokeAny() he invokeAll() 具有阻塞特性 invokeAny invokeAny 的作用是取得第一个完成任务的结果的值。 如果线程中增加 if (!Thread.currentThread().isInterrupted()) 判断&#xff0c;则会中断这些线程。 其他线程如果抛出 InterruptedException() 异常&a…

从徘徊迷茫到行业精英,社科院与杜兰大学金融管理硕士改变你的人生轨迹

在以“内卷”为主基调的职场环境里&#xff0c;似乎不停地进阶已经成为了职场人的唯一出路。但是&#xff0c;如何在进阶路上冲破职业瓶颈&#xff0c;到达心之所往的理想位置&#xff0c;则没有一个标准的答案。有的职场人士通过考取不同的技能证书来增加自身优势&#xff0c;…