Spring——SpringSecurity开发经验实战

摘要

本文介绍了一个简单的 Spring Security 实战示例,涵盖基本的身份验证和授权流程。首先介绍了 Spring Security 是一个强大的安全框架,用于在 Spring 应用中实现身份验证、授权以及保护应用免受常见安全攻击。接着详细阐述了项目结构、添加 Spring Security 依赖、创建数据库表、创建实体类、创建 UserDetailsService 实现、配置 Spring Security、使用@PreAuthorize注解控制方法权限、配置启动类、配置 application.properties 以及运行和测试等步骤。

1. Spring Security简介

Spring Security 是一个强大的安全框架,主要用于在 Spring 应用中实现身份验证、授权以及保护应用免受常见安全攻击。以下是一个简单的 Spring Security 实战示例,涵盖了基本的身份验证和授权流程。

2. 项目结构

src└── main├── java│    └── com│         └── example│              └── security│                   ├── SecurityConfig.java│                   ├── WebController.java│                   ├── Application.java│                   ├── CustomUserDetailsService.java│                   ├── User.java│                   ├── Role.java│                   └── UserRepository.java└── resources├── application.properties├── schema.sql└── data.sql

3. 添加 Spring Security 依赖

首先,确保在 pom.xmlbuild.gradle 中添加了 Spring Security 的依赖。

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

4. 创建数据库表

首先,我们需要为用户和角色创建数据库表。下面是一个简单的 SQL 脚本,用于在数据库中创建用户和角色表。

4.1. schema.sql 文件:

CREATE TABLE roles (id BIGINT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(50) NOT NULL
);CREATE TABLE users (id BIGINT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL UNIQUE,password VARCHAR(255) NOT NULL,enabled BOOLEAN NOT NULL DEFAULT true
);CREATE TABLE user_roles (user_id BIGINT,role_id BIGINT,PRIMARY KEY (user_id, role_id),FOREIGN KEY (user_id) REFERENCES users(id),FOREIGN KEY (role_id) REFERENCES roles(id)
);

4.2. data.sql 文件:

INSERT INTO roles (name) VALUES ('ROLE_ADMIN');
INSERT INTO roles (name) VALUES ('ROLE_USER');INSERT INTO users (username, password, enabled) VALUES ('admin', '{noop}admin', true);
INSERT INTO users (username, password, enabled) VALUES ('user', '{noop}user', true);INSERT INTO user_roles (user_id, role_id) 
SELECT u.id, r.id 
FROM users u, roles r 
WHERE u.username = 'admin' AND r.name = 'ROLE_ADMIN';INSERT INTO user_roles (user_id, role_id) 
SELECT u.id, r.id 
FROM users u, roles r 
WHERE u.username = 'user' AND r.name = 'ROLE_USER';

这里,{noop} 是 Spring Security 5 之前的一个标记,用于指示密码不加密。生产环境中应使用加密密码,如 BCrypt

5. 创建实体类

我们需要两个实体类 UserRole,分别表示用户和角色信息。

5.1. User.java

package com.example.security;import javax.persistence.*;
import java.util.Set;@Entity
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;private String password;private boolean enabled;@ManyToMany(fetch = FetchType.EAGER)@JoinTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))private Set<Role> roles;// Getters and Setters
}

5.2. Role.java

package com.example.security;import javax.persistence.*;@Entity
public class Role {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;// Getters and Setters
}

6. 创建 UserDetailsService 实现

我们将通过 UserDetailsService 从数据库加载用户信息,Spring Security 会使用这个服务来进行身份验证和权限控制。

6.1. CustomUserDetailsService.java

package com.example.security;import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import java.util.stream.Collectors;@Service
public class CustomUserDetailsService implements UserDetailsService {@Autowiredprivate final UserRepository userRepository;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 查询数据库,加载用户及其角色User user = userRepository.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("User not found"));// 将角色转换为 GrantedAuthorityreturn new User(user.getUsername(),user.getPassword(),user.isEnabled(),true, true, true,user.getRoles().stream().map(role -> new org.springframework.security.core.authority.SimpleGrantedAuthority(role.getName())).collect(Collectors.toList()));}
}

6.2. UserRepository.java

package com.example.security;import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;public interface UserRepository extends JpaRepository<User, Long> {Optional<User> findByUsername(String username);
}

7. 配置 Spring Security

SecurityConfig中,配置数据库认证,并启用方法级别的权限控制。

7.1. SecurityConfig.java

package com.example.security;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)  // 启用方法级权限控制
public class SecurityConfig {@Autowiredprivate final CustomUserDetailsService customUserDetailsService;@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/login", "/public/**").permitAll().anyRequest().authenticated().and().formLogin().permitAll().and().logout().permitAll();return http.build();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());}
}

8. 使用@PreAuthorize注解控制方法权限

在控制器方法上使用 @PreAuthorize 注解进行权限控制。比如,你可以根据角色控制谁能访问哪些页面。

8.1. WebController.java

package com.example.security;import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;@Controller
public class WebController {@GetMapping("/admin")@PreAuthorize("hasRole('ROLE_ADMIN')")  // 只有角色为 ROLE_ADMIN 的用户可以访问public String adminPage() {return "admin";}@GetMapping("/user")@PreAuthorize("hasRole('ROLE_USER')")   // 只有角色为 ROLE_USER 的用户可以访问public String userPage() {return "user";}@GetMapping("/dashboard")@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")  // 角色为 ROLE_ADMIN 或 ROLE_USER 的用户可以访问public String dashboard() {return "dashboard";}
}

9. 配置启动类

确保你有一个 Application 启动类来启动 Spring Boot 应用。

9.1. Application.java

package com.example.security;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

10. 配置 application.properties

确保你的 application.properties 中包含数据库连接配置。

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/security_db?useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.security.user.name=admin
spring.security.user.password=admin

11. 运行和测试

  1. 启动 Spring Boot 应用。
  2. 使用 adminuser 用户分别登录,访问 /admin/user/dashboard 页面,检查是否能根据角色权限控制访问。

这个示例展示了如何在 Spring Boot 中使用数据库存储用户和角色信息,并通过 @PreAuthorize 注解进行方法级别的权限控制。我们通过自定义 UserDetailsService 从数据库中加载用户信息并设置相应的角色。这样,Spring Security 会根据用户的角色来控制对不同控制器方法的访问权限。

博文参考

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Innovus中快速获取timing path逻辑深度的golden脚本

在实际项目中我们经常会遇到一条timing path级数特别多&#xff0c;可能是一两页都翻不完。此时&#xff0c;我们大都需要手工去数这条path上到底有哪些是设计本身的逻辑&#xff0c;哪些是PR工具插入的buffer和inverter。 数字IC后端手把手培训教程 | Clock Gating相关clock …

【Qt】桌面应用开发 ------ 绘图事件和绘图设备 文件操作

文章目录 9、绘图事件和绘图设备9.1 QPainter9.2 手动触发绘图事件9.3 绘图设备9.3.1 QPixmap9.3.2 QImage9.3.3 QImage与QPixmap的区别9.3.4 QPicture 10、文件操作10.1 文件读写10.2 二进制文件读写10.3 文本文件读写10.4 综合案例 9、绘图事件和绘图设备 什么时候画&#x…

数据结构绪论

一-数据结构的基本概念 1-数据 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。数据是计算机程序加工的原料。 2-数据元素 数据元素是数据的基本单位&#xff0c;通常作为一个整体进行考虑和处理。…

kafka基本知识

什么是 Kafka&#xff1f; Apache Kafka 是一个开源的分布式流处理平台&#xff0c;最初由 LinkedIn 开发&#xff0c;后来成为 Apache 软件基金会的一部分。Kafka 主要用于构建实时数据管道和流处理应用程序。它能够高效地处理大量的数据流&#xff0c;广泛应用于日志收集、数…

DeepSeek R1本地+私有云版医疗AI部署开发成功案例技术剖析

1. 引言 1.1 研究背景与意义 随着科技的飞速发展,人工智能(AI)在医疗领域的应用正逐渐成为推动医疗行业变革的重要力量。近年来,医疗 AI 取得了显著的进展,从疾病诊断、药物研发到医疗管理等各个环节,AI 技术都展现出了巨大的潜力。它能够处理和分析海量的医疗数据,为…

网络安全-openssl工具

OpenSSl是一个开源项目&#xff0c;包括密码库和SSL/TLS工具集。它已是在安全领域的事实标准&#xff0c;并且拥有比较长的历史&#xff0c;现在几乎所有的服务器软件和很多客户端都在使用openssl&#xff0c;其中基于命令行的工具是进行加密、证书管理以及测试最常用到的软件。…

“三次握手”与“四次挥手”:TCP传输控制协议连接过程

目录 什么是TCP协议 “三次握手”建立连接 “四次挥手”断开连接 “三次握手”和“四次挥手”的反思 总结 什么是TCP协议 想象一下&#xff0c;你和远方的朋友要进行一场电话交流&#xff0c;但这通电话不仅仅是随便聊聊&#xff0c;而是要传递一封重要的信件。为了确保这…

Visual Studio中打开多个项目

1) 找到解决方案窗口 2) 右键添加→ 选择现有项目 3) 选择.vcxproj文件打开即可

基于 Python Django 的校园互助平台(附源码,文档)

博主介绍&#xff1a;✌Java徐师兄、7年大厂程序员经历。全网粉丝13w、csdn博客专家、掘金/华为云等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不…

el-dropdown选中效果

vue2版本 <template><el-dropdown size"mini" command"handleCommand"><span class"el-dropdown-link">{{ selectedOption }}<i class"el-icon-arrow-down el-icon--right"></i></span><el-d…

Deepseek首页实现 HTML

人工智能与未来&#xff1a;机遇与挑战 引言 在过去的几十年里&#xff0c;人工智能&#xff08;AI&#xff09;技术取得了突飞猛进的发展。从语音助手到自动驾驶汽车&#xff0c;AI 正在深刻地改变我们的生活方式、工作方式以及社会结构。然而&#xff0c;随着 AI 技术的普及…

Linux(ubuntu) GPU CUDA 构建Docker镜像

一、创建Dockerfile FROM ubuntu:20.04#非交互式&#xff0c;以快速运行自动化任务或脚本&#xff0c;无需图形界面 ENV DEBIAN_FRONTENDnoninteractive# 安装基础工具 RUN apt-get update && apt-get install -y \curl \wget \git \build-essential \software-proper…

Rocky8 源码安装 HAProxy

HAProxy 是一款开源的高性能 负载均衡器 和 反向代理 软件&#xff0c;专注于处理高并发流量分发&#xff0c;广泛应用于企业级架构中提升服务的可用性、扩展性和安全性。 一、HAProxy 简介 1.1.HAProxy 是什么&#xff1f; 本质&#xff1a; 基于 C 语言开发 的轻量级工具&a…

JAVA最新版本详细安装教程(附安装包)

目录 文章自述 一、JAVA下载 二、JAVA安装 1.首先在D盘创建【java/jdk-23】文件夹 2.把下载的压缩包移动到【jdk-23】文件夹内&#xff0c;右键点击【解压到当前文件夹】 3.如图解压会有【jdk-23.0.1】文件 4.右键桌面此电脑&#xff0c;点击【属性】 5.下滑滚动条&…

Spring Boot 日志管理(官网文档解读)

摘要 本篇文章详细介绍了SpringBoot 日志管理相关的内容&#xff0c;文章主要参考官网文章的描述内容&#xff0c;并在其基础上进行一定的总结和拓展&#xff0c;以方便学习Spring Boot 的小伙伴能快速掌握Spring Boot 日志管理相关的内容。 日志实现方式 Sping Boot 的日志管…

【废物研究生零基础刷算法】DFS与递归(一)典型题型

文章目录 跳台阶递归实现指数级枚举递归实现排列型枚举上面两题总结 递归实现组合型枚举P1036选数 跳台阶 思路&#xff1a; 如果 n 1&#xff0c;只有一种走法&#xff08;走 1 级&#xff09;。如果 n 2&#xff0c;有两种走法&#xff08;11 或 2&#xff09;。对于 n &g…

百度首页上线 DeepSeek 入口,免费使用

大家好&#xff0c;我是小悟。 百度首页正式上线了 DeepSeek 入口&#xff0c;这一重磅消息瞬间在技术圈掀起了惊涛骇浪&#xff0c;各大平台都被刷爆了屏。 百度这次可太给力了&#xff0c;PC 端开放仅 1 小时&#xff0c;就有超千万人涌入体验。这速度&#xff0c;简直比火…

at32f103a+rtt+AT组件+esp01s 模块使用

AT组件使用 这里需要设置wifi名称和密码 配置使用的串口 配置上边的自动会配置,at_device 依赖了at_client 依赖sal也自动加入 依赖了串口2 uart2 连接WiFi AT+ CWJAP = TP-LINK_45A1

QT 基础知识点

1.基础窗口类QMainWindow qDialog Qwidget 随项目一起创建的窗口基类有三个可选QMainWindow qDialog Qwidget 1.1 Qwidget 是所有窗口的基类&#xff0c;只要是他的子类&#xff0c;或子类的子类&#xff0c;都具有他的属性。 右键项目 Add New -> Qt qt设计师界面类&am…

[漏洞篇]文件上传漏洞详解

[漏洞篇]文件上传漏洞详解 一、介绍 1. 概念 文件上传漏洞是指用户上传了一个可执行的脚本文件&#xff0c;并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的&#xff0c;“文件上传” 本身没有问题&#xff0c;有问题的是文件上传后&#xf…