【SpringBoot】之Security进阶使用

news2024/11/24 15:06:35

  🎉🎉欢迎来到我的CSDN主页!🎉🎉

🏅我是君易--鑨,一个在CSDN分享笔记的博主。📚📚

🌟推荐给大家我的博客专栏《SpringBoot开发之Security系列》。🎯🎯

🎁如果感觉还不错的话请给我关注加三连吧!🎁🎁


前言

        上一期的博客中我们一起了解了什么是Security,以及在SpringBoot中集成Security使用,以及一些的基础用法和一些案例演示。今天的这期博客基于上期博客进一步完善使用,请仔细阅读。

一、Security联合数据库使用(登陆功能)

1. 创建所需表

        在我们的数据库中国创建好我们所需要的表,有用户信息表、角色信息表、模块信息表(权限信息表)、用户角色表、角色模块表这五张表。用于后续的权限设置

表名说明
sys_user用户信息表
sys_role角色信息表
sys_module模块信息表(权限信息表)
sys_user_role用户角色表
sys_role_module角色模块表

 表之间的关系说明

         我们可以对用户信息表中的字段进行修改,只保留关键字段,也可以不修改。(我这里只保留了四个字段)

2. 配置文件 

         当然我们要连接数据库需要我们进行导入Mybatis-Plus的依赖以及数据库的依赖。

        当然还需要我们的生成器等等一些配置类 

 MySQLGenerator.java

package com.yx.security.config;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Slf4j
public class MySQLGenerator {

    private final static String URL = "jdbc:mysql://localhost:3306/bookshop";
    private final static String USERNAME = "root";
    private final static String PASSWORD = "root123";

    private final static DataSourceConfig.Builder DATA_SOURCE_CONFIG =
            new DataSourceConfig.Builder(URL, USERNAME, PASSWORD);

    public static void main(String[] args) {
        FastAutoGenerator.create(DATA_SOURCE_CONFIG)
                .globalConfig(
                        (scanner, builder) ->
                                builder.author(scanner.apply("请输入作者名称?"))
                                        .outputDir(System.getProperty("user.dir") + "\\src\\main\\java")
                                        .commentDate("yyyy-MM-dd")
                                        .dateType(DateType.TIME_PACK)
                                        .enableSwagger()
                )
                .packageConfig((builder) ->
                        builder.parent("com.zking.security")
                                .entity("pojo")
                                .service("service")
                                .serviceImpl("service.impl")
                                .mapper("mapper")
                                .xml("mapper.xml")
                                .pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "\\src\\main\\resources\\mapper"))
                )
                .injectionConfig((builder) ->
                        builder.beforeOutputFile(
                                (a, b) -> log.warn("tableInfo: " + a.getEntityName())
                        )
                )
                .strategyConfig((scanner, builder) ->
                        builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
                                .addTablePrefix("tb_", "t_", "lay_", "meeting_", "sys_", "t_medical_")
                                .entityBuilder()
                                .enableChainModel()
                                .enableLombok()
                                .enableTableFieldAnnotation()
                                .controllerBuilder()
                                .enableRestStyle()
                                .enableHyphenStyle()
                                .build()
                )
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();
    }

    protected static List<String> getTables(String tables) {
        return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
    }

}

        别忘记了根据项目信息进行修改 

 yml文件配置

server:
    port: 8080
spring:
    freemarker:
        # 设置freemarker模板后缀
        suffix: .ftl
        # 设置freemarker模板前缀
        template-loader-path: classpath:/templates/
        enabled: true
    datasource:
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password: 123456
        url: jdbc:mysql://localhost:3306/bookshop

生成对应的表

        我们这就只生成用户信息表。

 

        mapper记得打对应的注解,以及在项目启动类中加上扫描mapper的注解

3. 代码编写修改

  IndexController.java
package com.yx.security.controller;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {


    @RequestMapping("/")
    public String toLogin(){
        return "login";
    }

    @RequestMapping("/index")
    public String toIndex(){
        return "index";
    }


}
index.flt
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<h1>用户登录</h1>
<form action="/userLogin" method="post">
    <p>
        <label>用户:<input type="text" name="username"/></label>
    </p>
    <p>
        <label>密码:<input type="password" name="password"/></label>
    </p>
    <input type="submit" value="登录"/>
    <p>${msg!""}</p>
</form>
</body>
</html>

        首先在实体类中实现一个接口——UserDetails类,实现之后会进行一个重新编写四个方法。 

         但是重写方法是返回的值是死的,应该是重数据库中获取的返回值,因此改为定义四个属性及添加指定字段到表中。

         数据库表中的字段注意数驼峰命名用下滑线隔开,默认值都是1.,authorities不是数据库中的字段是代表权限的,待会在类上会打上注释说明,字段会打上注释说明是数据库上的那些字段。

        接下来就是实现功能的代码编写了,首先在实体接口实现类实现UserDetailsService,并且重新方法。

         对其配置类进行修改调整

         直接运行项目进行登陆

 演示

二、密码加密方式

1. 明文不加密

         如果存在多个密码加密方法,并都注释了@Bean注解,则可以用@Primary注解标记使用那个方法。

 2. 自定义MD5加密

        创建自定义MD5加密类并实现PasswordEncoder

PasswordEncoder.java

public class CustomMd5PasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence rawPassword) {
        //对密码进行 md5 加密
        String md5Password = DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes());
        System.out.println(md5Password);
        return md5Password;
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        // 通过md5校验
        System.out.println(rawPassword);
        System.out.println(encodedPassword);
        return encode(rawPassword).equals(encodedPassword);
    }
}

         修改SecurityConfig配置类,更换密码编码器

@Bean
public PasswordEncoder passwordEncoder(){
    // 自定义MD5加密方式:
    return new CustomMd5PasswordEncoder();
}

3. BCryptPasswordEncoder密码编码器

        BCryptPasswordEncoderSpring Security中一种基于bcrypt算法的密码加密方式。bcrypt算法是一种密码哈希函数,具有防止彩虹表攻击的优点,因此安全性较高。

        使用BCryptPasswordEncoder进行密码加密时,可以指定一个随机生成的salt值,将其与原始密码一起进行哈希计算。salt值可以增加密码的安全性,因为即使两个用户使用相同的密码,由于使用不同的salt值进行哈希计算,得到的哈希值也是不同的。

        在Spring Security中,可以通过在SecurityConfig配置类中添加以下代码来使用BCryptPasswordEncoder进行密码加密:

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

三、记住我功能实现(RememberMe )

        在实际开发中,为了用户登录方便常常会启用记住我(Remember-Me)功能。如果用户登录时勾选了“记住我”选项,那么在一段有效时间内,会默认自动登录,免去再次输入用户名、密码等登录操作。该功能的实现机理是根据用户登录信息生成 Token 并保存在用户浏览器的 Cookie 中,当用户需要再次登录时,自动实现校验并建立登录态的一种机制。

Spring Security提供了两种 Remember-Me 的实现方式:

  • 简单加密 Token:用散列算法加密用户必要的登录系信息并生成 Token 令牌。

  • 持久化 Token:数据库等持久性数据存储机制用的持久化 Token 令牌。

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. 修改SecurityConfig配置类

        Remember-Me 功能的开启需要在configure(HttpSecurity http)方法中通过http.rememberMe()配置,该配置主要会在过滤器链中添加 RememberMeAuthenticationFilter 过滤器,通过该过滤器实现自动登录。

        在配置类中添加一个方法

/**
	 * 配置持久化Token方式,注意tokenRepository.setCreateTableOnStartup()配置
	 */
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        // 设置为true要保障数据库该表不存在,不然会报异常哦
        // 所以第二次打开服务器应用程序的时候得把它设为false
        tokenRepository.setCreateTableOnStartup(false);
        return tokenRepository;
    }
    

         没创建表的可以将setCreateTableOmStartup的属性值该为true运行时会自动创建。

3. 前端添加组件

    <input type="checkbox" name="remember-me"/>记住我<br/>

4. 配置配置类获取组件

 .rememberMe()
                // 指定 rememberMe 的参数名,用于在表单中携带 rememberMe 的值。
                //.rememberMeParameter("remember-me")
                // 指定 rememberMe 的有效期,单位为秒,默认2周。
                .tokenValiditySeconds(30)
                // 指定 rememberMe 的 cookie 名称。
                .rememberMeCookieName("remember-me-cookie")
                // 指定 rememberMe 的 token 存储方式,可以使用默认的 PersistentTokenRepository 或自定义的实现。
                .tokenRepository(persistentTokenRepository())
                // 指定 rememberMe 的认证方式,需要实现 UserDetailsService 接口,并在其中查询用户信息。
                .userDetailsService(userDetailsService)

演示效果

        当我们删除网页重新访问主页时会直接进入不会需要登陆 ,数据库中也会生成对应数据,以及网页会生成Cookie

        当我们删除数据库表中的登陆信息数据时,重新刷新主页则访问不了 

四、CSRF防御

        CSRFCross-Site Request Forgery,跨站请求伪造)是一种利用用户已登录的身份在用户不知情的情况下发送恶意请求的攻击方式。攻击者可以通过构造恶意链接或者伪造表单提交等方式,让用户在不知情的情况下执行某些操作,例如修改密码、转账、发表评论等。

为了防范CSRF攻击,常见的做法是在请求中添加一个CSRF Token(也叫做同步令牌、防伪标志),并在服务器端进行验证。CSRF Token是一个随机生成的字符串,每次请求都会随着请求一起发送到服务器端,服务器端会对这个Token进行验证,如果Token不正确,则拒绝执行请求。

1.页面代码加入_csrf隐藏域

 <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

       不添加默认开启了防止跨域攻击的功能,任何 POST 提交到后台的表单都要验证是否带有 _csrf 参数,一旦传来的 _csrf 参数不正确,服务器便返回 403 错误。

如果针对一些特定的请求接口,不需要进行CSRF防御,可以通过以下配置忽略:

http.csrf().ignoringAntMatchers("/upload"); // 禁用/upload接口的CSRF防御

2. SpringSecurity中如何使用CSRF

        在Spring Security中,防范CSRF攻击可以通过启用CSRF保护来实现。启用CSRF保护后,Spring Security会自动在每个表单中添加一个隐藏的CSRF Token字段,并在服务器端进行验证。如果Token验证失败,则会抛出异常,从而拒绝执行请求。启用CSRF保护的方式是在Spring Security配置文件中添加.csrf()方法,例如:

  http.csrf().disable();是禁用CSRF

3. 测试

         我们复制一份登陆表单不携带csrf隐藏域进行测试

        由上图所知,第一个登陆添加了csrf隐藏域能够成功访问主页,第二个登陆没有添加则无法访问。


.csrf()主要方法介绍:
方法说明
disable()关闭CSRF防御
csrfTokenRepository()设置CookieCsrfTokenRepository实例,用于存储和检索CSRF令牌。与HttpSessionCsrfTokenRepository不同,CookieCsrfTokenRepositoryCSRF令牌存储在cookie中,而不是在会话中。
ignoringAntMatchers()设置一组Ant模式,用于忽略某些请求的CSRF保护。例如,如果您想要忽略所有以/api/开头的请求,可以使用.ignoringAntMatchers("/api/**")
csrfTokenManager()设置CsrfTokenManager实例,用于管理CSRF令牌的生成和验证。默认情况下,Spring Security使用DefaultCsrfTokenManager实例来生成和验证CSRF令牌。
requireCsrfProtectionMatcher()设置RequestMatcher实例,用于确定哪些请求需要进行CSRF保护。默认情况下,Spring Security将对所有非GET、HEAD、OPTIONS和TRACE请求进行CSRF保护。

🎉🎉本期的博客分享到此结束🎉🎉

📚📚各位老铁慢慢消化📚📚

🎯🎯下期博客博主会带来新货🎯🎯

🎁三连加关注,阅读不迷路 !🎁

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

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

相关文章

解决 Linux git push 贡献者不同(没有出现绿点)的问题

第一步&#xff0c;通过下面的指令&#xff0c;修改 linux git 的配置文件&#xff1a; vi ~/.gitconfig会进入下图界面&#xff1a; 进入本地&#xff08;Windows&#xff09;中 git 的设置界面 复制 名称 和 Email 到 gitconfig 里&#xff0c;不要在末尾加 &#xff08;空…

直排轮滑教程4

蹬地 1&#xff0c;前面练习了蹬地的结构&#xff0c;知道蹬地方向&#xff0c;如何用力。下面来练习具体的蹬地的方法&#xff0c;轮滑蹬地有自己特点。 2&#xff0c;技术方法和特点&#xff1a;蹬地速度快&#xff0c;蹬地有弹性。似跳非跳蹬。 3&#xff0c;四轮着地。轮…

使用PE信息查看工具和Beyond Compare文件比较工具排查dll文件版本不对的问题

目录 1、问题说明 2、修改了代码&#xff0c;但安装版本还是有问题 3、使用PE信息查看工具查看音视频库文件&#xff08;二进制&#xff09;的时间戳 4、使用Beyond Compare比较两个库文件的差异 5、找到原因 6、最后 C软件异常排查从入门到精通系列教程&#xff08;专栏…

NFS原理详解

一、NFS介绍 1&#xff09;什么是NFS 它的主要功能是通过网络让不同的机器系统之间可以彼此共享文件和目录。 NFS服务器可以允许NFS客户端将远端NFS服务器端的共享目录挂载到本地的NFS客户端中。 在本地的NFS客户端的机器看来&#xff0c;NFS服务器端共享的目录就好像自己的磁…

【蓝桥杯】树的重心

树的重心 图的dfs模板 int dfs(int u) {st[u]true;for(int ih[u];i!-1;ine[i]){int je[i];if(!st[j]){dfs(j);}} }树是这样的。 邻接表&#xff1a; 1: 4->7->2->-1 2: 5->8->1->-1 3: 9->4->-1 4: 6->3->1->-1 5: 2->-1 6: 4->-1 7…

计算机网络 运输层下 | TCP概述 可靠传输 流量控制 拥塞控制 连接管理

文章目录 3 运输层主要协议 TCP 概述3.1 TCP概述 特点3.2 TCP连接RSVP资源预留协议 4 TCP可靠传输4.1 可靠传输工作原理4.1.1 停止等待协议4.1.2 连续ARQ协议 4.2 TCP可靠通信的具体实现4.2.1 以字节为单位的滑动窗口4.2.2 超时重传时间的选择4.2.3 选择确认SACK 5 TCP的流量控…

Python---socket之send和recv原理剖析

1. 认识TCP socket的发送和接收缓冲区 当创建一个TCP socket对象的时候会有一个发送缓冲区和一个接收缓冲区&#xff0c;这个发送和接收缓冲区指的就是内存中的一片空间。 2. send原理剖析 send是不是直接把数据发给服务端? 不是&#xff0c;要想发数据&#xff0c;必须得…

GEE-Sentinel-2月度时间序列数据合成并导出

系列文章目录 第一章&#xff1a;时间序列数据合成 文章目录 系列文章目录前言时间序列数据合成总结 前言 利用每个月可获取植被指数数据取均值&#xff0c;合成月度平均植被指数&#xff0c;然后将12个月中的数据合成一个12波段的时间数据合成数据。 时间序列数据合成 代码…

嵌入式中断理解

一、概念 中断&#xff1a; 在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&#xff0c;处理完成后又返回原来被暂停的位置继续运行。 中断优先级&#x…

YACS(上海计算机学会竞赛平台)一星级题集——水仙花指数

题目描述 定义一个正整数的十进制表示中各位数字的立方和为它的水仙花指数&#xff0c;给定一个整数 n&#xff0c;请计算它的水仙花指数。 例如 n1234 时&#xff0c;水仙花指数为 输入格式 单个整数&#xff1a;表示 n 输出格式 单个整数&#xff1a;表示 n 的水仙花指…

IPC之九:使用UNIX Domain Socket进行进程间通信的实例

socket 编程是一种用于网络通信的编程方式&#xff0c;在 socket 的协议族中除了常用的 AF_INET、AF_RAW、AF_NETLINK等以外&#xff0c;还有一个专门用于 IPC 的协议族 AF_UNIX&#xff0c;IPC 是 Linux 编程中一个重要的概念&#xff0c;常用的 IPC 方式有管道、消息队列、共…

深入探讨开源对话系统:IntelliQ的世界

在人工智能的快速发展时代&#xff0c;开源项目成为了推动技术革新的重要力量。最近&#xff0c;我注意到了一个特别有趣的项目——IntelliQ。这个项目旨在利用大型语言模型&#xff08;LLM&#xff09;构建一个多轮问答系统&#xff0c;不仅具备强大的意图识别和词槽填充&…

【Unity】【WebRTC】如何用Unity而不是浏览器接收远程画面

【背景】 之前几篇我们讨论了如何设置信令服务器&#xff0c;如何发送画面给远端以及如何用浏览器查看同步画面&#xff0c;今天来讨论如何实现Unity内部接收画面。 看本篇之前请先看过之前将web服务器设置和基本远程画面功能的几篇博文。&#xff08;同专栏下查看&#xff09…

使用VSC从零开始Vue.js——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务3:数据可视化

使用Visual Studio Code&#xff08;VSC&#xff09;进行Vue开发非常方便&#xff0c;下面是一些基本步骤&#xff1a; 一、下载和安装Vue 官网下载地址Download | Node.js Vue.js是基于Node.js的&#xff0c;所以首先需要安装Node.js&#xff0c;官网下载地址&#xff1a;No…

PMP项目管理 - 范围管理

系列文章目录 系统架构设计 PMP项目管理 - 整合管理 PMP项目管理 - 质量管理 PMP项目管理 - 采购管理 PMP项目管理 - 资源管理 PMP项目管理 - 风险管理 PMP项目管理 - 沟通管理 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is …

快速搭建Grafana Promethus 服务器监控系统

该文参考文章&#xff0c;其中又遇到一些问题&#xff0c;并解决&#xff0c;当前主要为了记录一下 探针 Grafana Prometheus 之比 Docker 更简单的部署流程 - 承飞之咎本文重在 Grafana Prometheus 探针 方案的部署流程&#xff0c;介绍和更多使用请到&#xff1a;探针 ̵……

【12.20】转行小白历险记 登录+注册页

一、登录注册页面逻辑 写样式布局&#xff1a;垂直居中、编程式路由、调后端接口正则表达式验证用户输入的密码规则校验通过后&#xff0c;跳转页面js兜底校验调后端接口将token值存储到vuex中&#xff0c;实现持久化存储 vuex不是持久化存储的&#xff0c;如果需要持久化存储…

当下流行的直播技术demo演示

nginx-http-flv-module&#xff08;更新不是很频繁&#xff09; SRS: https://ossrs.net/lts/zh-cn/&#xff08;独立官网&#xff0c;目前最新稳定版version5&#xff09; 基于SRS搭建直播demo演示&#xff1a; 一、搭建流媒体服务器 参见官网&#xff1a;https://ossrs.ne…

Windows 如何在局域网中建立NTP服务器实现时间同步(设置一台设备作为主机,其他设备作为从机来同步时间)

首先简单了解一下什么是NTP 网络时间协议(NTP)是一种用于同步计算机网络上各设备时间的协议。NTP时间同步在许多项目和应用中都是关键的&#xff0c;特别是那些对时间同步精度有要求的场景。比如需要使用NTP时间同步的情况有&#xff1a;金融交易系统、科学研究实验、工业自动…

ROS笔记之rosbag的快速切片(C++实现)

ROS笔记之rosbag的快速切片(C实现) —— 杭州 2023-12-21 夜 code review 文章目录 ROS笔记之rosbag的快速切片(C实现)1.运行效果2.文件结构3.fast_rosbag_slice.cpp4.CMakeLists.txt5.package.xml6.对fast_rosbag_slice.cpp进行函数封装 正常该功能是ROS官方命令行&#xff1a…