Spring Boot 整合 Spring Security

article/2025/8/3 23:23:33

DAY30.1 Java核心基础

Spring Boot 整合安全框架

Spring Security 、Shiro

Spring Security

Spring Security 的核心功能包括认证、授权、攻击防护,通过大量的过滤器和拦截器进行请求的拦截和验证,实现安全校验的功能。

Spring Security 将校验逻辑分发到不同的拦截器中,一个拦截器负责一种验证,比如UsernamePassword拦截器就是专门用来验证用户名和密码是否正确的,它会拦截登入请求,检查是否包含了用户名和密码,同时进行验证,如果没有则放行进入下一个拦截器

1、pom中添加依赖

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

2、创建一个index页面

<!DOCTYPE html>
<!--导入thymeleaf配置-->
<html lang="en" xmlns:th="http://www.thymeleaf.org"></html>
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<h1>hello</h1></body>
</html>

3、访问页面(如果没登入认证)会跳转到 Spring Security 的登入验证界面

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

这个页面是Spring Security自带的页面,导入了依赖包就有了

然后用户名密码默认为user,密码为启动的时候生成的密码image-20250529223308283

然后他在拦截器UsernamePasswordAuthenticationFilter进行拦截验证的

4、配置Spring Security的账号密码

spring:security:user:name: adminpassword: 123456

除了登入的时候,Security还可以用于权限验证,比如admin账号可以访问所有页面,user角色账号只能访问某些界面,怎么实现呢?

创建一个配置类SecurityConfig
package org.nanfengspringboot01.config;import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {/*** 定义角色* @param auth* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().passwordEncoder(new PasswordEncoderImpl()).withUser("user").password(new PasswordEncoderImpl().encode("123")).roles("USER").and().withUser("admin").password(new PasswordEncoderImpl().encode("123")).roles("USER","ADMIN");}/*** 定义权限* @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/admin").hasRole("ADMIN").antMatchers("/index").access("hasRole('ADMIN') or hasRole('USER')").anyRequest().authenticated().and().formLogin().loginPage("/login").permitAll().and().logout().permitAll().and().csrf().disable();}
}
还需要一个实现类PasswordEncoderImpl
public class PasswordEncoderImpl implements PasswordEncoder {@Overridepublic String encode(CharSequence rawPassword) {return rawPassword.toString();}@Overridepublic boolean matches(CharSequence rawPassword, String encodedPassword) {return encodedPassword.equals(rawPassword.toString());}
}

解释一下配置代码:

http.authorizeRequests()

开始配置 URL 的访问权限控制。

.antMatchers("/admin").hasRole("ADMIN")

访问 /admin 页面必须具备 ADMIN 角色。

.antMatchers("/index").access("hasRole('ADMIN') or hasRole('USER')")

访问 /index 页面,要求用户拥有 ADMINUSER 角色中的任意一个。

.anyRequest().authenticated()

除了 /admin/index 外,其他所有请求都必须登录后才能访问。

.and()
.formLogin()
.loginPage("/login")
.permitAll()

配置表单登录:

  • 登录页面为 /login(你需要自己定义一个该路径的登录页面)
  • 所有人都可以访问该登录页面(不需要登录)
.and()
.logout()
.permitAll()

配置登出功能:

  • 所有人都可以访问登出接口
.and()
.csrf()
.disable();

禁用 CSRF(跨站请求伪造)防护机制。

✅ 适合前后端分离、或使用 JWT 登录验证的项目。否则生产环境最好不要关闭 CSRF 防护。

控制器
@Controller
public class IndexController {@GetMapping("/index")private String index(){return "index";}@GetMapping("/admin")private String admin(){return "admin";}@GetMapping("/login")private String login(){return "login";}
}

访问页面index.html

会自动跳转到login.html登入界面

image-20250530160030670

但是user账户登入之后访问不了admin界面,因为user没有访问admin界面的权限

image-20250530160108229

连接数据库获取账号信息

创建数据库表Account

create table account(id int PRIMARY key auto_increment,username VARCHAR(11),password VARCHAR(11),role VARCHAR(11)
)

配置用户信息,注意role的写法需要写出ROLE_USER这样的格式,这个是Security的解析格式

image-20250530165855285

创建实体类

@Data
@Entity
public class Account  {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;@Columnprivate String username;@Columnprivate String password;@Columnprivate String role;
}

创建 AccountRepository,实现登录方法

@Repository
public interface AccountResitory extends JpaRepository<Account,Integer> {public Account findByUsername(String username);
}

重写UserDetailsService接口的loadUserByUsername方法,从数据库获取密码 ,返回一个User对象

@Service
public class UserDetailServiceImpl implements UserDetailsService {@Autowiredprivate AccountResitory accountResitory;/*** 通过重新这个方法来改变验证匹配密码的逻辑* @param username* @return* @throws UsernameNotFoundException*/@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {Account account = accountResitory.findByUsername(username);if(account==null){throw new UsernameNotFoundException("用户不存在");}else {String password = account.getPassword();Collection<GrantedAuthority> authorities = new ArrayList<>();SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(account.getRole());authorities.add(simpleGrantedAuthority);return new User(username,password,authorities);}}
}

修改Security的配置类,将这个UserDetailsService注入

auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailService;/*** 定义用户角色* @param auth* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth.inMemoryAuthentication().passwordEncoder(new PasswordEncoderImpl())
//                .withUser("user").password(new PasswordEncoderImpl().encode("123")).roles("USER")
//                .and()
//                .withUser("admin").password(new PasswordEncoderImpl().encode("123")).roles("USER","ADMIN");auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());}@Beanpublic PasswordEncoder passwordEncoder() {return NoOpPasswordEncoder.getInstance();}/*** 定义权限* @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/admin").hasRole("ADMIN").antMatchers("/index").access("hasRole('ADMIN') or hasRole('USER')").anyRequest().authenticated().and().formLogin().loginPage("/login").permitAll().and().logout().permitAll().and().csrf().disable();}
}

http://www.hkcw.cn/article/ZsURXOpWmZ.shtml

相关文章

深度剖析Node.js的原理及事件方式

早些年就接触过Node.js&#xff0c;当时对于这个连接前后端框架就感到很特别。尤其是以独特的异步阻塞特性&#xff0c;重塑了了服务器端编程的范式。后来陆陆续续做了不少项目&#xff0c;通过实践对它或多或少增强了不少理解。今天&#xff0c;我试着将从将从原理层剖析其运行…

智慧景区一体化建设方案

随着2023年文旅部《关于推动智慧旅游发展的指导意见》出台&#xff0c;全国景区掀起数字化转型浪潮。如何在激烈竞争中脱颖而出&#xff1f;智慧景区一体化建设方案&#xff0c;正以“一机游遍景区、一屏掌控全局”的革新模式&#xff0c;重新定义旅游体验与管理效率。本文深度…

使用 SymPy 操作三维向量的反对称矩阵

在三维空间中&#xff0c;一个 3 1 3 \times 1 31 向量可以转换为一个 3 3 3 \times 3 33 的反对称矩阵。这种转换在物理学、机器人学和计算机视觉等领域非常有用。本文将详细介绍如何在 Python 的 SymPy 库中定义和使用这种反对称矩阵。 数学背景 对于一个三维向量 v …

LangChain表达式(LCEL)实操案例1

案例1&#xff1a;写一篇短文&#xff0c;然后对这篇短文进行打分 from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.runnables import RunnableWithMessageHist…

CppCon 2014 学习:HOW UBISOFT MONTREAL DEVELOPS GAMES FOR MULTICORE

多核处理器&#xff08;Multicore Processor&#xff09; 的基本特性&#xff0c;下面是对每点的简要说明&#xff1a; &#x1f539; Multicore&#xff08;多核&#xff09; 指一个物理处理器上集成了 多个 CPU 核心&#xff0c;每个核心可以独立执行指令。 &#x1f538;…

STL解析——String类详解(使用篇)

目录 sring接口解析 1.string简介 2.默认成员函数 2.1构造函数 2.2析构函数 2.3赋值重载 3.迭代器 3.1初识迭代器 3.2迭代器的使用 3.3特殊迭代器 3.4范围for 4.大小接口 4.1字符长度相关接口 4.2空间大小相关接口 5.其他常用接口 5.1operator[ ] 5.2增 5.3查 5…

Android 代码阅读环境搭建:VSCODE + SSH + CLANGD(详细版)

在阅读Android源码&#xff08;AOSP超过1亿行代码&#xff09;时&#xff0c;开发者常面临索引失败、跳转卡顿等问题。本教程将手把手教你搭建基于VSCode SSH Clangd的终极阅读环境&#xff0c;实现秒级符号跳转、精准代码提示和高效远程开发。 一、环境架构解析 1.1 方案组…

JAVA 集合的进阶 泛型的继承和通配符

1 泛型通配符 可以对传递的类型进行限定 1.1 格式 ? 表示不确定的类型 &#xff1f;extends E&#xff1a; 表示可以传递 E 或者 E 所有的子类类型 &#xff1f;super E&#xff1a; 表示可以传递 E 或者 E 所有的父类类…

改写自己的浏览器插件工具 myChromeTools

1. 起因&#xff0c; 目的: 前面我写过&#xff0c; 自己的一个浏览器插件小工具 最近又增加一个小功能&#xff0c;可以自动滚动页面&#xff0c;尤其是对于那些瀑布流加载的网页。最新的代码都在这里 2. 先看效果 3. 过程: 代码 1, 模拟鼠标自然滚动 // 处理滚动控制逻辑…

由sigmod权重曲线存在锯齿的探索

深度学习的知识点&#xff0c;一般按照执行流程&#xff0c;有 网络层类型&#xff0c;归一化&#xff0c;激活函数&#xff0c;学习率&#xff0c;损失函数&#xff0c;优化器。如果是研究生上课学的应该系统一点&#xff0c;自学的话知识点一开始有点乱。 一、激活函数Sigmod…

仿腾讯会议——优化:多条tcp连接

1、添加用户信息结构 2、添加注册视频音频结构体 3、 完成函数注册视频音频

File—IO流

因为变量&#xff0c;数组&#xff0c;对象&#xff0c;集合这些数据容器都在内存中&#xff0c;一旦程序结束&#xff0c;或者断电&#xff0c;数据就丢失了。想要长久保存&#xff0c;就要存在文件中&#xff08;File&#xff09; 文件可以长久保存数据。 文件在电脑磁盘中…

【Zephyr 系列 2】用 Zephyr 玩转 Arduino UNO / MEGA,实现串口通信与 CLI 命令交互

🎯 本篇目标 在 Ubuntu 下将 Zephyr 运行在 Arduino UNO / MEGA 上 打通串口通信,实现通过串口发送命令与反馈 使用 Zephyr Shell 模块,实现 CLI 命令处理 🪧 为什么 Arduino + Zephyr? 虽然 Arduino 开发板通常用于简单的 C/C++ 开发,但 Zephyr 的支持范围远超 STM32…

最悉心的指导教程——阿里云创建ECS实例教程+Vue+Django前后端的服务器部署(通过宝塔面板)

各位看官老爷们&#xff0c;点击关注不迷路哟。你的点赞、收藏&#xff0c;一键三连&#xff0c;是我持续更新的动力哟&#xff01;&#xff01;&#xff01; 阿里云创建ECS实例教程 注意&#xff1a; 阿里云有300元额度的免费适用期哟 白嫖~~~~ 注册了阿里云账户后&#x…

【Android】如何抓取 Android 设备的 UDP/TCP 数据包?

目录 前言理解抓包tcpdump 实时抓包Wireshark 解包抓包后的一些思考 前言 在真正接触 UDP/TCP 抓包之前&#xff0c;我一直以为这是一项高深莫测的技术。可当我们真正了解之后才发现&#xff0c;其实并没有那么复杂——不过如此。 所谓的大佬&#xff0c;往往只是掌握了你尚未…

VR看房系统,新生代看房新体验

VR看房系统的概念 虚拟现实&#xff08;VirtualReality,VR&#xff09;看房系统&#xff0c;是近年来随着科技进步在房地产行业中兴起的一种创新看房方式。看房系统利用先进的计算机技术模拟出一个三维环境&#xff0c;使用户能够身临其境地浏览和体验房源&#xff0c;无需亲自…

机器学习Day5-模型诊断

实现机器学习算法的技巧。当我们训练模型或使用模型时&#xff0c;发现预测误差很 大&#xff0c;可以考虑进行以下优化&#xff1a; &#xff08;1&#xff09;获取更多的训练样本 &#xff08;2&#xff09;使用更少的特征 &#xff08;3&#xff09;获取其他特征 &#xff…

STM32F103_Bootloader程序开发06 - IAP升级用的App.bin增加CRC32校验码,确保固件完整性,防止“变砖”

导言 《STM32F103_Bootloader程序开发05 - Keil修改生成文件的路径与文件名&#xff0c;自动生成bin格式文件》上一章节成功让Keil生成App.bin二进制文件&#xff0c;用于IAP升级。 为了保障IAP升级过程中的固件完整性&#xff0c;避免因损坏文件导致设备“变砖”&#xff0c;…

语言使用的国家概况统计

语言是文化的载体&#xff0c;也是沟通和协作的桥梁。随着全球化进程加快&#xff0c;了解主要语言的分布及其使用国家&#xff0c;对于数据分析师、产品经理、市场人员乃至技术开发者&#xff0c;都极为重要。本文将梳理全球几种主要语言&#xff08;英语、法语、阿拉伯语、俄…

DeepSeek-R1-0528

深度思考能力强化​ DeepSeek-R1-0528 仍然使用 2024 年 12 月所发布的 DeepSeek V3 Base 模型作为基座&#xff0c;但在后训练过程中投入了更多算力&#xff0c;显著提升了模型的思维深度与推理能力。 更新后的 R1 模型在数学、编程与通用逻辑等多个基准测评中取得了当前国内…