Spring Security实战(三)—— 自动登录与注销登录

news2025/2/27 3:43:03

目录

一、实现自动登录

 1. 散列加密方案

2. 持久化令牌方案

 二、注销登录


一、实现自动登录

        自动登录是将用户的登录信息保存在用户浏览器的cookie中,当用户下次访问时,自动实现校验并建立登录态的一种机制。

        Spring Security 提供了两种非常好的令牌:

  • 用散列算法加密用户必要的登录信息并生成令牌
  • 数据库等持久性数据存储机制用的持久化令牌

 1. 散列加密方案

(1)增加自动登录功能

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(new CaptchaFilter(),UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
                .antMatchers("/admin/api/**").hasRole("ADMIN")
                .antMatchers("/user/api/**").hasRole("USER")
                //开放验证码的访问权限
                .antMatchers("/captcha.jpg").permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
            .formLogin()
                .loginPage("/login.html")
                .permitAll()
                .and()
                //记住我
                .rememberMe().userDetailsService(userDetailsService);
    }

(2)在登录页中增加remember me复选框

<label><input type="checkbox" name="remember-me" id="remember-me">Remember Me</label>

(3)按照正常流程登录

在浏览器的开发者工具中查看cookie,可以看到多了一个 remember-me,这就是Spring Security默认自动登录的cookie字段。在不配置的情况下,过期时间是两个星期。

但是现在会有一个问题,每次重启服务后,这个KEY(remember-me)都会重新生成,所以每次重启服务我们还需要再进行登录,这就就谈不上自动登录了。

合理的用法是指定KEY。如:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(new CaptchaFilter(),UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
                .antMatchers("/admin/api/**").hasRole("ADMIN")
                .antMatchers("/user/api/**").hasRole("USER")
                //开放验证码的访问权限
                .antMatchers("/captcha.jpg").permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
            .formLogin()
                .loginPage("/login.html")
                .permitAll()
                .and()
                .rememberMe().userDetailsService(userDetailsService)
        .key("zy");//指定key
    }

这样,重启服务之后登录后,就算再一次重启服务也不需要再登录,这就实现了自动登录功能。

2. 持久化令牌方案

         持久化令牌方案在交互上与散列加密方案一致,都是在用户勾选 Remember-me之后,将生成的令牌发送到用户浏览器,并在用户下次访问系统时读取该令牌进行认证。不同的是,它采用更加严谨的安全性设计。

        在持久化令牌方案中,最核心的是seriestoken两个值,它们都是用MD5散列过的随机字符串。不同的是,series仅在用户使用密码重新登陆时更新,而token会在每一个新的session中都重新生成。

这样设计的好处

        首先,解决了散列加密方案中一个令牌可以同时在多端登录的问题。每个会话都会引发token的更新,即每个token仅支持单实例登录

        其次,自动登录不会导致series变更,而每次自动登录都需要同时验证series和token两个值,当该令牌还未使用过自动登陆就被盗取时,系统会在非法用户验证通过后刷新token值,此时在合法用户的浏览器中,该token值已经失效。当合法用户使用自动登录时,由于该series对应的token不同,系统可以推断该令牌可能已经被盗用,从而做出一些处理。如清理该用户的所有自动登录的令牌,并通知该用户可能已经被盗号。

(1)在数据库新建一张 persistent_logins表

CREATE TABLE persistent_logins (
    username VARCHAR(64) NOT NULL,
    series VARCHAR(64) NOT NULL,
    token VARCHAR(64) NOT NULL,
    last_used TIMESTAMP NOT NULL,
    PRIMARY KEY (series)
);

(2)配置spring security的Remember-me功能

由于需要使用持久化令牌方案,所以定制 tokenRepository,tokenRepository() 括号里需要传入一个PersistentTokenRepository实例,这里我们使用JdbcTokenRepositoryImpl,JdbcTokenRepositoryImpl 是基于DataSource实现对应SQL操作的类,所以我们需要指定DataSource。

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //指定dataSource
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        http
                .addFilterBefore(new CaptchaFilter(),UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
                .antMatchers("/admin/api/**").hasRole("ADMIN")
                .antMatchers("/user/api/**").hasRole("USER")
                //开放验证码的访问权限
                .antMatchers("/captcha.jpg").permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
            .formLogin()
                .loginPage("/login.html")
                .permitAll()
                .and()
                .rememberMe()
                .userDetailsService(userDetailsService)
        .tokenRepository(jdbcTokenRepository);
    }

(3)重启服务

重启服务并登录之后,再次重启服务,可以实现自动登录

 经base64解码:

JSESSIONID=E76686FEE7637DEB4F1E5C9E8A930A6F;
Idea-b5baabb9=16077984-579b-44d2-a1a2-92f5837858ef;
remember-me=1K3%24%2FLnZb590SKpZlTlpHg%3D%3D:eduptdyzPFt8x2wQI2QLA==

冒号前的部分是series,冒号后的部分是token。当自动登录认证时,Spring Security通过series获取用户名、token、以及上一次自动登陆时间三个信息。

  • 通过用户名确认该令牌的身份
  • 通过对比token获知该令牌是否有效
  • 通过上一次自动登录的时间获知该令牌是否过期

在完整校验通过之后生成新的token。 

(4)查看数据库信息

 二、注销登录

        认证系统往往都带有注销登录功能,Spring Security 也提供了这方面的支持。事实上,从我们编写配置类继承 WebSecurityConfigurerAdapter 的那一刻起,Spring Security 就已经为我们的系统埋入了注销的逻辑。

        HttpSecurity 内的 logout() 方法以一个 LogoutConfigurer 作为配置基础,创建一个用于注销登录的过滤器。

        它默认注册了一个 /logout 路由,用户通过访问该路由可以安全地注销其登录状态,包括使HttpSession 失效、清空已配置的 Remember-me 验证,以及清空 SecurityContextHolder,并在注销成功之后重定向到 /login?logout页面。

也可以自定义配置,如:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //指定dataSource
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        http
                .addFilterBefore(new CaptchaFilter(),UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
                .antMatchers("/admin/api/**").hasRole("ADMIN")
                .antMatchers("/user/api/**").hasRole("USER")
                //开放验证码的访问权限
                .antMatchers("/captcha.jpg").permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
            .formLogin()
                .loginPage("/login.html")
                .permitAll()
                .and()
                .rememberMe()
                .userDetailsService(userDetailsService)
        .tokenRepository(jdbcTokenRepository)
        .and()
        .logout()
        .logoutUrl("/myLogout")//配置接收注销请求的路由
        .logoutSuccessUrl("/login.html")//注销成功后跳转到 login.html页面
        .logoutSuccessHandler(new LogoutSuccessHandler() {
            @Override
            public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                System.out.println("用户成功退出");
            }
        })
        .invalidateHttpSession(true) //使用户的HttpSession失效
        .deleteCookies("cookie1","cookie2") //注销成功 删除指定的cookie
        .addLogoutHandler(new LogoutHandler() {
            @Override
            public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
                System.out.println("已经注销了!");
            }
        });
    }

实际上,logout的清理过程是由多个LogoutHandler流式处理的。

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

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

相关文章

C ++ 基础入门。加强变量、指针、结构体理解

1、 const放外面&#xff0c;值不可以改。只读 同理于指针 看const右侧紧跟着的是指针还是常量, 是指针就是常量指针&#xff0c;是常量就是指针常量 const 放外面&#xff0c;值不可以改 2、 所有的指针类型&#xff0c;包括结构体指针 double * int *都是和操作系统位数…

补充——spark RDD序列化和持久化

目录 RDD序列化 闭包检查&#xff1a; 序列化方法和属性 Kryo序列化框架&#xff1a; RDD持久化&#xff08;RDD persistence&#xff09; RDDCache缓存 RDD persist缓存 什么时候使用persist()? RDD CheckPoint 检查点 缓存和检查点区别 RDD序列化 闭包检查&#x…

JavaScript 的基础函数有哪些?

1、在 JavaScript 中将数组本地转换为对象 JavaScript 有一个原生函数 Object.fromEntries&#xff0c;可用于将任何输入数组转换为对象。 1.const anArray [ 2. [firstname, Paul], 3. [surname, Knulst], 4. [address, worldwide], 5. [role, Senior Engineer], 6. […

Java中的异常Exception和捕获,自定义异常

文章目录1. 异常概述1.1 什么是程序的异常1.2 异常的抛出机制1.3 如何对待异常2. Java异常体系2.1 Throwable2.2 Error 和 Exception2.3 编译时异常和运行时异常3. 常见的错误和异常3.1 Error3.2 运行时异常3.3 编译时异常4. 异常的处理4.1 异常处理概述4.2 捕获异常&#xff0…

springboot整合websocket

1.创建springboot项目&#xff0c;引入spring-boot-starter-websocket依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>全部依赖如下&#xff1a; &l…

JDBC之DAO层封装思想超详解

Mysql版本&#xff1a;8.0.26 可视化客户端&#xff1a;sql yog 编译软件&#xff1a;IntelliJ IDEA 2019.2.4 x64 运行环境&#xff1a;win10 家庭中文版 jdk版本&#xff1a;1.8.0_361 目录一、DAO是什么&#xff1f;二、案例演示2.1 准备数据2.2 创建bean包2.3 建立DAO包2.2…

Houdini>RBD(搅拌大米效果)并导出FBX到unity

Houdini&#xff1e;RBD(搅拌大米效果) 效果展示&#xff1a; 动图录制软件&#xff1a;Cockos Incorporated | LICEcap 参考链接&#xff1a;导出除了ABC外&#xff0c;比较小的FBX文件用法 目录&#xff1a; 一、引用模型的处理&#xff1a; 1、大米 模型创建 多层复制 …

Mybatis(六)缓存

缓存是Mybatis中非常重要的特性&#xff0c;Mybatis的一级缓存基于SqlSession实现&#xff0c;二级缓存基于Mapper实现。 一、缓存的使用 一级缓存默认开启&#xff0c;Mybatis提供了一个配置参数localCacheScope来控制一级缓存的级别&#xff0c;该参数的取值可以是session、…

【机器学习】P10 从头到尾实现一个线性回归案例

这里写自定义目录标题&#xff08;1&#xff09;导入数据&#xff08;2&#xff09;画出城市人口与利润图&#xff08;3&#xff09;计算损失值&#xff08;4&#xff09;计算梯度下降&#xff08;5&#xff09;开始训练&#xff08;6&#xff09;画出训练好的模型&#xff08;…

参加Matlab与AI讲座:使用深度强化学习训练走路机器人观后感

时间&#xff1a;2023年4月12日&#xff0c;周三&#xff0c;天气晴 地址&#xff1a;大连理工大学研教楼303 前言&#xff1a;Matlab其实有很多功能&#xff0c;我们所用的只是最基础最简单的部分&#xff0c;例如矩阵计算&#xff0c;画图等等。 随着强化学习的发展&#xff…

一般形式的S曲线公式推导

文章目录一、背景二、目标三、计算3.1 S曲线基本形式3.2 S曲线变换3.3 参数计算3.4 S曲线中心对称条件四、总结五、附件一、背景 S曲线因具备良好可控的平滑性、单调性、连续可导性等优点&#xff0c;常作为各类电机升降速曲线。当前多数S曲线的介绍文章未给出推导过程&#x…

SpringCloud微服务技术栈.黑马跟学(五)

SpringCloud微服务技术栈.黑马跟学 五今日目标1.初识elasticsearch1.1.了解ES1.1.1.elasticsearch的作用1.1.2.ELK技术栈1.1.3.elasticsearch和lucene1.1.4.为什么不是其他搜索技术&#xff1f;1.1.5.总结1.2.倒排索引1.2.1.正向索引1.2.2.倒排索引1.2.3.正向和倒排1.3.es的一些…

SpringMVC基本注解的使用和理解

SpringMVC基本注解的使用和理解 RequestParam注解 使用在方法入参位置&#xff0c;用于指定请求参数名称&#xff0c;将该请求参数绑定到注解参数位置。 属性&#xff1a;name:指定要绑定的请求参数名称&#xff1b; name属性和value属性互为别名。 required 和&#xff1a;指…

Java并发编程(8) —— AQS抽象同步队列详解

上一篇&#xff1a;Java并发编程(7) —— 锁的分类概述 在上一篇中我们提到并发包中的ReentrantLock类是一种可重入独占锁&#xff0c;其锁机制是基于AQS实现的。实际上&#xff0c;并发包java.util.concurrent.locks中的锁都是基于AQS 实现的。 一、AQS是什么 AbstractQueued…

13. unity粒子特效--发射模块、各种发射器形状、粒子渐变(颜色/大小)

1. 发射模块&#xff08;Emission&#xff09; 匀速发射&#xff1a; Rate over Time&#xff1a;每秒钟发射的粒子数 Rate over Distance&#xff1a;每移动一米发射的粒子个数 两者可指定其一&#xff1a;若仅指定Rate over Time&#xff0c;则粒子根据时间的变化进行发射&a…

第三节、语言模型

目录 0、介绍 1、N-gram 模型介绍 2、困惑度 3、N-gram 模型的文本评估 4、N-gram 模型的平滑 5、基于 N-gram 模型的文本生成 6、基于统计的语言模型的缺陷 7、实验总结 0、介绍 首先&#xff0c;我们来思考这样一个问题&#xff1a;随便给你一句话&#xff0c;如何判…

MongoDB中的索引

一、说明 索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可能要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是…

Javaweb小练习---在JSP中使用Javabean访问数据库完成用户信息的简单添加

Javaweb小练习---在JSP中使用Javabean访问数据库完成用户信息的简单添加 目录 Javaweb小练习---在JSP中使用Javabean访问数据库完成用户信息的简单添加 0.创建数据库 1. 在resources目录下创建db.properties文件 2. /** * 获取链接与释放资源的工具类--JdbcUtil类 */ 3…

UE-Ueransim-5GC全链路开发记录

目录 1. 系统配置 1.1 Ueransim配置 1.2 UE配置 2. 启动 3. 实际演示 附录 代理1&#xff1a;ueransim-5gc 代理2 ue-ueransim TCPclient TCPserver 1. 系统配置 1.1 Ueransim配置 ueransim的yaml文件如下 version: 3.8 services:ueransim2:container_name: uera…

Ubantu docker学习笔记(六)容器数据卷

文章目录一、容器数据卷二、容器卷挂载2.1 在命令行挂载数据卷2.2 通过dockerfile挂载数据卷三、数据卷容器四、备份数据卷五、数据卷的恢复和迁移5.1 恢复数据卷5.2 迁移数据卷六、管理数据卷6.1 与容器关联&#xff08;1&#xff09;例子一&#xff08;2&#xff09;例子二&a…