【SpringBoot3】Spring Security 常用配置总结

news2024/12/22 13:56:27

注:本文基于Spring Boot 3.2.1 以及 Spring Security 6.2.1

相关文章

【SpringBoot3】Spring Security 核心概念
【SpringBoot3】Spring Security 常用注解
【SpringBoot3】Spring Security 详细使用实例(简单使用、JWT模式)
【SpringBoot3】Spring Security使用mybatis-plus存储用户角色权限,实现动态权限处理

一、Spring Security 常用配置总结

1、记住我 rememberMe

1)配置HttpSecurity,如下代码

// 开启rememberMe,登录表单增加 <input type="checkbox" name="remember-me">
http.rememberMe(Customizer.withDefaults());

2)登录表单页面增加勾选参数,在登录时勾选即可

注意参数名remember-me是默认的,也可以通过配置修改

<input type="checkbox" name="remember-me">

登录成功后,会生成一个cookie(remember-me)

3)配置rememberMe其他参数

  • rememberMeParameter,表单参数名称
  • rememberMeCookieName,记录在浏览器的cookieName
  • tokenValiditySeconds,有效时间,单位秒
http.rememberMe(rm -> rm
        .rememberMeParameter("rememberMe")
        .rememberMeCookieName("rememberMeCookieName")
        .key("rememberMe")
        .tokenValiditySeconds(1800));

2、退出处理

// 退出时,设置session无效
http.logout(logout -> logout.invalidateHttpSession(true));

3、持久化登录令牌

持久化登录令牌是记住我功能的补充,可以将登录的token存储在数据库中。

参考 JdbcTokenRepositoryImpl 可以得知需要创建一张表 persistent_logins

本例使用 mybatis-plus + mysql 存储

1)创建持久化令牌表 persistent_logins

create table persistent_logins (username varchar(64) not null, series varchar(64) primary key,  token varchar(64) not null, last_used timestamp not null)

2)创建实体和Mapper

@Data
@TableName("persistent_logins")
public class UserToken {
    private String username;

    private String series;

    @TableField("token")
    private String tokenValue;
    @TableField("last_used")
    private Date date;
}

@Mapper
public interface UserTokenMapper extends BaseMapper<UserToken> {
}

3)创建自定义持久化类 MyPersistentTokenRepositoryImpl 实现接口 PersistentTokenRepository

@Service
public class MyPersistentTokenRepositoryImpl implements PersistentTokenRepository {
    @Resource
    private UserTokenMapper userTokenMapper;

    @Override
    public void createNewToken(PersistentRememberMeToken token) {
        UserToken userToken = BeanUtil.toBean(token, UserToken.class);
        userTokenMapper.insert(userToken);
    }

    @Override
    public void updateToken(String series, String tokenValue, Date lastUsed) {
        LambdaUpdateWrapper<UserToken> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(UserToken::getSeries, series)
                .set(UserToken::getTokenValue, tokenValue)
                .set(UserToken::getDate, lastUsed);
        userTokenMapper.update(updateWrapper);
    }

    @Override
    public PersistentRememberMeToken getTokenForSeries(String seriesId) {
        UserToken userToken = userTokenMapper.selectOne(new LambdaQueryWrapper<UserToken>().eq(UserToken::getSeries, seriesId));
        PersistentRememberMeToken meToken = BeanUtil.toBean(userToken, PersistentRememberMeToken.class);
        return meToken;
    }

    @Override
    public void removeUserTokens(String username) {
        userTokenMapper.delete(new LambdaQueryWrapper<UserToken>().eq(UserToken::getUsername, username));
    }
}

4)在 HttpSecurity 中配置使用

@Resource
private MyPersistentTokenRepositoryImpl tokenRepository;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    
    // --- 忽略其他代码 --- //
    
    http.rememberMe(rm -> rm
            .rememberMeParameter("rememberMe")
            .rememberMeCookieName("rememberMeCookieName")
            .key("rememberMe")
            // 配置持久化类
            .tokenRepository(tokenRepository)
            .tokenValiditySeconds(1800));
     
     // --- 忽略其他代码 --- //
}

5)登录,勾选记住我
在这里插入图片描述
打开数据库查看,存储正常

在这里插入图片描述

4、并发登录控制,后登录踢掉前面登录

设置每个账户最大的session数量

// 每个账户最大的session数量
http.sessionManagement(sm->sm.maximumSessions(1));

5、主动踢人下线

1)配置 SessionRegistry

/**
 * 通过 SessionRegistry 可以获取到当前登录的所有用户
 * @return
 */
@Bean
public SessionRegistry sessionRegistry(){
    return new SessionRegistryImpl();
}

在 HttpSecurity 中配置

// 每个账户最大的session数量,配置 sessionRegistry
http.sessionManagement(sm->sm.maximumSessions(1).sessionRegistry(sessionRegistry()));

2)在controller中获取在线用户,并展示

@GetMapping("/index")
public String index(Model model) {
    // 获取所有登录过的用户
    List<Object> allPrincipals = sessionRegistry.getAllPrincipals();
    // 移除不存在session的用户
    List<Object> list = allPrincipals.stream().filter(p -> {
        List<SessionInformation> allSessions = sessionRegistry.getAllSessions(p, false);
        return !allSessions.isEmpty();
    }).toList();
    model.addAttribute("users", list);
    return "index";
}

在 index.html中显示

<table>
    <tr>
        <th>用户名</th>
        <th>操作</th>
    </tr>
    <tr th:each="user:${users}">
        <td th:text="${user.username}"></td>
        <td><a th:href="@{/kickout(username=${user.username})}">下线</a></td>
    </tr>
</table>

3)增加踢人接口

@GetMapping("/kickout")
public String kickout(String username) {
    List<Object> allPrincipals = sessionRegistry.getAllPrincipals();
    for (Object principal : allPrincipals) {
        List<SessionInformation> allSessions = sessionRegistry.getAllSessions(principal, false);
        User user = (User) principal;
        if (user.getUsername().equals(username)) {
            //将所有已登录的 session 都失效
            allSessions.forEach(SessionInformation::expireNow);
        }
    }
    return "redirect:/index";
}

6、允许跨域处理

什么是跨域

CORS跨域,全称是“跨域资源共享”(Cross-Origin Resource Sharing),是一种基于HTTP标头的机制,它允许服务器指示除其自身之外的任何来源(域、方案或端口),浏览器应允许从中加载资源。这种机制允许浏览器向跨源服务器发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

当浏览器从一个源(域)向另一个源(域)发出请求时,由于安全原因,浏览器会限制这种跨源请求。但是,CORS通过服务器和浏览器的协商,允许某些跨源请求得以通过。具体来说,浏览器会先向服务器发送一个“预检”请求,检查服务器是否允许实际请求。如果服务器允许,那么浏览器就会发送实际的跨域请求。

CORS需要浏览器和服务器同时支持,目前几乎所有的浏览器都支持CORS,但IE浏览器不能低于IE10版本。实现CORS的关键在于服务器,只要服务器实现了CORS接口,就可以实现跨域通信。

Spring Security 配置允许跨域

配置 HttpSecurity

// 开启跨域
http.cors(Customizer.withDefaults())

7、跨域攻击防护

什么是CSRF

CSRF,全称是跨站请求攻击(Cross-Site Request Forgery),是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。简单来说,攻击者通过一些技术手段欺骗用户的浏览器去访问一个用户之前已经认证过的站点,并运行一些操作,如发邮件、发消息,甚至进行财产操作(如转账和购买商品)等。由于浏览器之前已经认证过,被访问的站点会误以为是真正的用户操作而去运行。这种攻击利用了Web中用户身份认证验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。因此,CSRF攻击可以被理解为攻击者盗用了用户的身份,以用户的名义发送恶意请求。

为了防范CSRF攻击,Web应用程序可以采取一些措施,如使用验证码、检查请求来源、使用CSRF令牌等。这些措施可以增加攻击的难度,降低攻击成功的可能性。同时,用户也应该保持警惕,不要随意点击不明链接或下载未知来源的文件,以保护自己的隐私和财产安全。

Spring Security 处理 CSRF

默认情况下,Spring Security 会自动启用 CSRF 保护,这包括在表单中包含 CSRF 令牌(token)并在处理请求时验证这个令牌。

// 开启csrf 保护
http.csrf(Customizer.withDefaults());

在登录表单中,会自动生成参数_csrf ,如下所示:

在这里插入图片描述

参考

  • https://docs.spring.io/spring-security/reference/index.html

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

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

相关文章

Docusaurus框架——快速搭建markdown文档站点介绍sora

文章目录 ⭐前言⭐初始化项目&#x1f496; 创建项目&#xff08;react-js&#xff09;&#x1f496; 运行项目&#x1f496; 目录文件&#x1f496; 创建一个jsx页面&#x1f496; 创建一个md文档&#x1f496; 创建一个介绍sora的文档 ⭐总结⭐结束 ⭐前言 大家好&#xff0…

智能风控体系之PagePank算法应用

PageRank算法&#xff0c;即网页排名算法&#xff0c;由Google创始人Larry Page在斯坦福上学的时候提出来的。该算法用于对网页进行排名&#xff0c;排名高的网页表示该网页被访问的概率高。PageRank算法计算每一个网页的PageRank值&#xff0c;然后根据这个值的大小对网页的重…

Linux笔记之LD_LIBRARY_PATH详解

Linux笔记之LD_LIBRARY_PATH详解 文章目录 Linux笔记之LD_LIBRARY_PATH详解1.常见使用命令来设置动态链接库路径2.LD_LIBRARY_PATH详解设置 LD_LIBRARY_PATH举例注意事项 3.替代方案使用标准路径编译时指定链接路径优先使用 rpath 还是 runpath&#xff1f;注意事项 1.常见使用…

高级RAG:重新排名,从原理到实现的两种主流方法

原文地址&#xff1a;https://pub.towardsai.net/advanced-rag-04-re-ranking-85f6ae8170b1 2024 年 2 月 14 日 重新排序在检索增强生成&#xff08;RAG&#xff09;过程中起着至关重要的作用。在简单的 RAG 方法中&#xff0c;可以检索大量上下文&#xff0c;但并非所有上下…

Android 解决后台服务麦克风无法录音问题

Android 解决后台无法录音问题 问题分析问题来源解决方案1. 修改清单文件:`AndroidManifest.xml`2. 修改启动服务方式3. 服务启动时创建前台通知并且指定前台服务类型参考文档最后我还有一句话要说我用心为你考虑黄浦江的事情,你心里想的却只有苏州河的勾当 问题分析 安卓9.…

NPM私服搭建(verdaccio)

官网地址&#xff1a;https://verdaccio.org/ 概述 Verdaccio 是一个流行的 Node.js 包管理器的代理工具&#xff0c;它允许您在本地或私有网络上轻松地创建和管理 npm 包仓库。通过 Verdaccio&#xff0c;开发团队可以建立自己的 npm 包仓库&#xff0c;以更好地控制和管理其依…

Linux:Jenkins:GitLab+Maven+Jenkins的部署

1.环境 我这里准备了三台centos7 1.用于部署gitlab 运行内存&#xff1a;6G 名字&#xff1a;Jenkins-GitLab 192.168.6.1 2.用于部署jenkins 运行内存&#xff1a;2G 名字&#xff1a;Jenkins-server 192.168.6.2 3.用于打包测试…

设计模式——三大工厂模式

工厂模式 简单工厂模式&#xff08;静态工厂模式&#xff09; 介绍&#xff1a; 1、简单工厂模式是属于创建型模式&#xff0c;是工厂模式的一种&#xff0c;**简单工厂模式是由一个工厂对象决定创建出哪种产品的实例**。是工厂模式中最简单使用的模式 2、简单工厂模式&#…

ONLYOFFICE8.0——赋能办公

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-xdAoM2pHRmDFP0tF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

挑战30天学完Python:Day18 正则表达式

&#x1f4d8; Day 18 &#x1f389; 本系列为Python基础学习&#xff0c;原稿来源于 30-Days-Of-Python 英文项目&#xff0c;大奇主要是对其本地化翻译、逐条验证和补充&#xff0c;想通过30天完成正儿八经的系统化实践。此系列适合零基础同学&#xff0c;或仅了解Python一点…

Python 在Word中创建表格并填入数据、图片

在Word中&#xff0c;表格是一个强大的工具&#xff0c;它可以帮助你更好地组织、呈现和分析信息。本文将介绍如何使用Python在Word中创建表格并填入数据、图片&#xff0c;以及设置表格样式等。 Python Word库&#xff1a; 要使用Python在Word中创建或操作表格&#xff0c;需…

24款奔驰C260L升级C63包围 渣男的外观

今天店里来了一台24款奔驰C260L 一提车就过来升级 我们公司还有包上牌服务 车主说 升级完包围 帮忙安排一下 原车的包围 没有那么霸气 特别是后杠 光溜溜的 升级后 四出尾喉 尾翼 直接牌面就起来了&#xff0c;星骏汇小许Xjh15863

【统计分析数学模型】判别分析(四):机器学习分类算法

【统计分析数学模型】判别分析&#xff08;四&#xff09;&#xff1a;机器学习分类算法 一、机器学习分类算法1. 交叉验证方法2. 案例数据集3. 数据标准化 二、决策树模型1. 基本原理2. 计算步骤3. R语言实现 三、K最邻近分类1. 基本原理2. K值的选择3. R语言实现 四、支持向量…

图像压缩感知的MATLAB实现(OMP)

前面实现了 压缩感知的图像仿真&#xff08;MATLAB源代码&#xff09; 效果还不错&#xff0c;缺点是速度慢如牛。 下面我们采用OMP对其进行优化&#xff0c;提升速度。具体代码如下&#xff1a; 仿真 构建了一个MATLAB文件&#xff0c;所有代码都在一个源文件里面&#xf…

MySQL——基础内容

目录 第01章_数据库概述 关系型数据库(RDBMS)——表、关系模型 非关系型数据库(非RDBMS) 表、记录、字段 表的关联关系 一对一关联 一对多关系 多对多 自我引用 第02章_MySQL环境搭建 登录命令 常用命令 show databases; create database use 数据库名 show tables 第03章…

2023最新简绘AI开源版支持MJ绘画,AI问答

应用介绍 本文来自&#xff1a;2023最新简绘AI开源版支持MJ绘画&#xff0c;AI问答 - 源码1688 简介&#xff1a; 简绘AI开源版&#xff0c;从闲鱼上买的&#xff0c;搭建教程如下 测试环境&#xff1a;NginxPHP7.4MySQL5.6 图片&#xff1a;

CentOS 中 RSYNC 同步分发脚本一键部署

文章目录 一、场景说明二、脚本职责三、参数说明四、操作示例五、注意事项 一、场景说明 本自动化脚本旨在为提高研发、测试、运维快速部署应用环境而编写。 脚本遵循拿来即用的原则快速完成 CentOS 系统各应用环境部署工作。 统一研发、测试、生产环境的部署模式、部署结构、…

ChatGpt的初步认知(认知搬运工)

前言 ChatGpt火了有一段时间了&#xff0c;对各行各业也有了一定的渗透&#xff0c;当然发展过程中也做了一些安全约束&#xff0c;今天主要是来跟大家分享下关于chatGpt的初步认知。 一、chatGpt是什么&#xff1f; ChatGPT&#xff0c;全称聊天生成预训练转换器&#xff08;英…

如何利用AI产品写作高质量SEO文章

在搜索引擎优化&#xff08;SEO&#xff09;的过程中&#xff0c;我们的目标非常明确&#xff0c;即增加网站的流量并实现有效的转化。那么&#xff0c;如何才能吸引更多的用户访问网站呢&#xff1f;这时候&#xff0c;文章就成为了一个非常好的工具。用户可以通过阅读文章来了…

How to implement multiple file uploads based on Swagger 3.x in Spring boot 3.x

How to implement multiple file uploads based on Swagger 3.x in Spring boot 3.x Projectpom.xmlOpenAPIConfigFileUploadControllerapplication.yaml Project pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://…