后端进阶之路——万字总结Spring Security与数据库集成实践(五)

news2024/11/15 23:39:21

前言

在这里插入图片描述
「作者主页」:雪碧有白泡泡
「个人网站」:雪碧的个人网站
「推荐专栏」

java一站式服务
前端炫酷代码分享
uniapp-从构建到提升
从0到英雄,vue成神之路
解决算法,一个专栏就够了
架构咱们从0说
★ 数据流通的精妙之道★

★后端进阶之路★

请添加图片描述

文章目录

  • 前言
  • 1. 引言
    • 使用数据库集成Spring Security的目的和好处
  • 2. 数据库设计与配置
    • 2.1 用户表的结构和字段
    • 2.2 角色表的结构和字段
    • 2.3 配置Spring Security与数据库的连接
  • 3. 用户认证
    • 3.1 实现基于数据库的用户认证功能
    • 3.2 使用Spring Security的Encoder进行密码加密和验证
    • 4.3 自定义用户认证的逻辑和处理方式
  • 4. 用户授权
    • 4.1 基于数据库的用户授权功能
    • 4.2 在数据库中定义角色和权限
    • 4.3 配置权限验证规则和授权方式
    • 4.4 自定义用户授权的逻辑和处理方式
  • 小结

在这里插入图片描述

1. 引言

使用数据库集成Spring Security的目的和好处

  1. 数据库作为存储用户信息的可靠源:将用户信息存储在数据库中可以保证其持久性和安全性,并且可方便地进行管理和维护。

  2. 灵活的用户认证和授权配置:通过数据库集成,可以实现对不同用户的不同认证和授权方式,例如基于角色的访问控制或基于权限的细粒度控制。

  3. 可拓展性和可定制化:通过数据库集成,可以轻松地添加新的用户、角色和权限,并且能够根据具体需求进行自定义身份验证和授权逻辑的开发。

  4. 统一管理用户信息:通过数据库集成,可以实现统一管理用户信息。当用户信息发生变化时,例如更改密码、添加或删除角色等,只需在数据库中进行修改即可。

在本文中,我们将深入探讨如何将Spring Security与数据库集成,实现基于数据库的用户身份验证和授权。我们将介绍Spring Security的基本概念和功能,讨论数据库设计和配置的具体细节,并提供完整的示例代码来演示这种集成方式的实际应用。通过阅读本文,读者将能够理解和应用这种集成方式,构建安全可靠的认证和授权系统。

在这里插入图片描述

2. 数据库设计与配置

在使用数据库进行身份验证和授权时,我们需要设计和配置适合存储用户信息和角色信息的数据库结构。这些信息通常存储在两张表中:用户表和角色表。

2.1 用户表的结构和字段

用户表通常包含以下字段:

  • id: 用户的唯一标识符
  • username: 用户名
  • password: 经过加密的密码
  • enabled: 标识用户是否启用(例如,激活状态)
  • 其他可选字段,如emailphone

以下是一个示例用户表的SQL定义:

CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(64) NOT NULL,
  password VARCHAR(256) NOT NULL,
  enabled BOOLEAN NOT NULL,
  email VARCHAR(128),
  phone VARCHAR(16)
);

2.2 角色表的结构和字段

角色表用于定义不同用户角色,并且与用户表之间存在关联。角色表通常包含以下字段:

  • id: 角色的唯一标识符
  • name: 角色名称

以下是一个示例角色表的SQL定义:

CREATE TABLE roles (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(64) NOT NULL
);

2.3 配置Spring Security与数据库的连接

在Spring Security中配置与数据库的连接,需要提供数据库的连接信息、用户名、密码等配置。我们可以使用Spring的配置文件(如application.properties)或Java配置类来配置数据库连接。

以下是一个示例的application.properties文件配置数据库连接:

spring.datasource.url=jdbc:mysql://localhost:3306/security_db
spring.datasource.username=db_username
spring.datasource.password=db_password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

在Spring Security配置中,我们需要配置一个UserDetailsService,它负责从数据库中加载用户信息并提供给Spring Security进行身份验证和授权。

以下是一个示例的Java配置类示例,其中配置了UserDetailsService

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery("SELECT username, password, enabled FROM users WHERE username = ?")
                .authoritiesByUsernameQuery("SELECT u.username, r.name FROM users u, roles r, user_roles ur WHERE u.id = ur.user_id AND r.id = ur.role_id AND u.username = ?");
    }

    // Other security configurations...
}

在上述示例中,我们通过dataSource注入配置的数据库连接。usersByUsernameQueryauthoritiesByUsernameQuery用于自定义查询用户信息和角色/权限的SQL语句。

通过以上的数据库设计和配置,我们可以建立一个与Spring
Security集成的数据库,以存储用户和角色信息,并通过配置文件或Java配置类与Spring
Security建立连接。这将为我们的身份验证和授权提供基础。

3. 用户认证

用户认证是确保用户身份有效性的过程。在基于数据库的用户认证中,我们将使用Spring Security来实现用户认证功能。

3.1 实现基于数据库的用户认证功能

通过配置UserDetailsService,我们可以从数据库中加载用户信息,并将其与用户提交的凭据进行比较以验证其身份。

以下是一个示例的UserDetailsService实现类,用于从数据库中加载用户信息:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found");
        }
        return new org.springframework.security.core.userdetails.User(
                user.getUsername(),
                user.getPassword(),
                user.getAuthorities()
        );
    }
}

在上述示例中,我们注入了UserRepository,该接口用于查询数据库中的用户信息。

3.2 使用Spring Security的Encoder进行密码加密和验证

为了保护用户密码的安全性,我们需要对密码进行加密并进行比较。Spring Security提供了多种加密方式,例如BCrypt、SHA-256等。

以下是一个示例的密码加密和验证示例:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService())
            .passwordEncoder(passwordEncoder);
    }

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

    // Other security configurations...
}

在上述示例中,我们配置了一个PasswordEncoder bean,并将其注入到AuthenticationManagerBuilder中。这样,当用户登录时,Spring Security会自动将用户输入的密码与数据库中存储的加密密码进行比较。

4.3 自定义用户认证的逻辑和处理方式

通过实现UserDetailsService接口和使用PasswordEncoder,我们可以实现基于数据库的用户认证。但有时我们可能需要自定义用户认证的逻辑和处理方式。

以下是一个示例的自定义用户认证的配置示例:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticationProvider());
    }

    @Bean
    public AuthenticationProvider customAuthenticationProvider() {
        CustomAuthenticationProvider authenticationProvider = new CustomAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        return authenticationProvider;
    }

    // Other security configurations...
}

在上述示例中,我们实现自定义的CustomAuthenticationProvider,并将其注册为AuthenticationProviderCustomAuthenticationProvider可以实现自定义的用户认证逻辑,例如通过额外的验证步骤、读取其他系统的用户信息等。

以下是一个示例的CustomAuthenticationProvider类:

public class CustomAuthenticationProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;
    private PasswordEncoder passwordEncoder;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();

        UserDetails userDetails = userDetailsService.loadUserByUsername(username);

        if (passwordEncoder.matches(password, userDetails.getPassword())) {
            return new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
        } else {
            throw new BadCredentialsException("Invalid credentials");
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
    }

    // Setter methods for UserDetailsService and PasswordEncoder
}

在上述示例中,我们通过UserDetailsService加载用户信息,并使用PasswordEncoder验证密码。如果用户认证通过,我们创建一个UsernamePasswordAuthenticationToken对象来表示成功的认证。

通过自定义用户认证逻辑和处理方式,我们可以灵活地应对各种特定的认证需求,如双因素身份验证、第三方认证等。

通过以上的实现和配置,我们可以实现基于数据库的用户认证。Spring Security将会验证用户提交的凭证,并根据数据库中的用户信息进行身份验证。为了保障密码的安全性,我们可以使用SpringSecurity提供的加密方式对密码进行加密和验证。同时,如果需要自定义用户认证逻辑和处理方式,我们可以实现自己的CustomAuthenticationProvider来满足特定的需求。
在这里插入图片描述

4. 用户授权

用户授权是为了确定用户能够访问系统中特定资源的权限。在基于数据库的用户授权功能中,我们将使用数据库中定义的角色和权限进行授权操作。

4.1 基于数据库的用户授权功能

通过配置Spring Security,我们可以使用数据库中定义的角色和权限对用户进行授权。

以下是一个示例的权限验证规则和授权方式的配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasAnyRole("ADMIN", "USER")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .logout();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    // Other security configurations...
}

在上述示例中,我们通过antMatchers定义了不同URL路径的权限验证规则。例如,"/admin/“路径需要具有"ADMIN"角色才能访问,而”/user/"路径需要具有"ADMIN"或"USER"角色才能访问。

4.2 在数据库中定义角色和权限

为了实现基于数据库的用户授权功能,我们需要在数据库中定义角色和权限。

以下是一个示例的角色表和权限表的定义:

CREATE TABLE roles (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(64) NOT NULL
);

CREATE TABLE permissions (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(64) NOT NULL
);

然后,我们需要定义用户与角色之间的关联,以及角色与权限之间的关联。

以下是一个示例的用户角色关联表和角色权限关联表的定义:

CREATE TABLE user_roles (
   user_id INT NOT NULL,
   role_id INT NOT NULL,
   PRIMARY KEY (user_id, role_id),
   FOREIGN KEY (user_id) REFERENCES users(id),
   FOREIGN KEY (role_id) REFERENCES roles(id)
);

CREATE TABLE role_permissions (
   role_id INT NOT NULL,
   permission_id INT NOT NULL,
   PRIMARY KEY (role_id, permission_id),
   FOREIGN KEY (role_id) REFERENCES roles(id),
   FOREIGN KEY (permission_id) REFERENCES permissions(id)
);

通过以上的数据库定义,我们可以在数据库中建立用户、角色和权限的关联关系,并在用户授权时使用。

4.3 配置权限验证规则和授权方式

在上述的Spring Security配置中,我们使用antMatchers定义了访问路径的权限验证规则,并指定了需要具有哪些角色才能访问对应的路径。

除了使用角色进行访问控制外,我们也可以使用权限进行访问控制。权限是角色的组成部分,每个角色可以具有多个权限。

以下是一个示例的权限验证规则和授权方式的配置,基于数据库中的角色和权限:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/admin/**").hasAuthority("ADMIN_ACCESS")
            .antMatchers("/user/**").hasAnyAuthority("ADMIN_ACCESS", "USER_ACCESS")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .logout();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    // Other security configurations...
}

在上述示例中,我们使用hasAuthorityhasAnyAuthority来配置权限验证规则。例如,"/admin/“路径需要具有"ADMIN_ACCESS"权限才能访问,而”/user/"路径需要具有"ADMIN_ACCESS"或"USER_ACCESS"权限才能访问。

4.4 自定义用户授权的逻辑和处理方式

通过自定义UserDetailsServiceAuthenticationProvider,我们可以实现自定义的用户授权逻辑和处理方式。

例如,在UserDetailsService中,我们可以根据具体的业务逻辑从数据库中加载用户信息和授权信息。在AuthenticationProvider中,我们可以实现自定义的授权逻辑,例如根据用户的其他属性进行额外的授权判断。

通过自定义用户授权的逻辑和处理方式,我们可以灵活地定义和调整系统中的权限控制方式,以满足不同的业务需求。

小结

这篇文章的主要目标是展示如何将Spring Security与数据库集成,实现基于数据库的用户身份认证和授权。通过引入数据库,并配合Spring Security的功能和配置,可以构建一个安全可靠的用户认证和授权系统
在这里插入图片描述

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

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

相关文章

K8S系列文章之 一键部署K8S环境

部署的原理是基于自动化部署工具 Ansible 实现的&#xff0c;需要提前安装Ansible 并配置下主机节点环境 1. 安装 Ansible 首先ansible基于python2.X 环境&#xff0c;默认centos都已经安装好了python2环境 // 最好更新下库 // yum update yum install -y epel-release yum i…

ctfshow-web5

0x00 前言 CTF 加解密合集CTF Web合集 0x01 题目 0x02 Write Up 首先看到代码&#xff0c;发现要求v1必须是字符串&#xff0c;v2必须是数字&#xff0c;并且对v1和v2的md5弱相等&#xff0c;也就是&#xff0c;只比较字符串开头是否相等&#xff0c;那么就需要找到两个md5开…

Mac系统下使用远程桌面连接Windows系统

一、远程桌面工具 Microsoft Remote Desktop 二、下载地址 https://go.microsoft.com/fwlink/?linkid868963 三、下载并安装 四、添加远程PC PC name:云服务器IP。 User account: 添加系统用户 PC name&#xff1a;远程桌面 IP 地址User account&#xff1a;可以选择是…

RabbitMQ 教程 | 第11章 RabbitMQ 扩展

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

机器学习、人工智能、深度学习三者的区别

目录 1、三者的关系 2、能做些什么 3、阶段性目标 1、三者的关系 机器学习、人工智能&#xff08;AI&#xff09;和深度学习之间有密切的关系&#xff0c;它们可以被看作是一种从不同层面理解和实现智能的方法。 人工智能&#xff08;AI&#xff09;&#xff1a;人工智能是一…

【网络编程·传输层】UDP和TCP的报头

目录 一、端口号划分 二、部分指令 1、pidof&#xff08;用于查看进程id&#xff09; 2、netstat&#xff08;查看网络状态&#xff09; 三、UDP协议 1、UDP协议格式 2、UDP协议如何进行封装、解包、分用 2.1封装、解包 2.2分用 3、UDP协议的特点 3.1UDP协议的特点 …

外部链接跳转到vue项目传递参数实现单点登录

1、问题背景描述&#xff1a; 我有一个困扰了很久项目需求&#xff0c;前台门户用的MVC&#xff0c;前台登录之后需要能点击某个按钮就能进入后台vue开发的前端项目&#xff0c;不需要重新登录。这个需求中mvc项目相对于vue项目来说是外部链接&#xff0c;他要跳转到vue项目&a…

HarmonyOS应用开发的新机遇与挑战

HarmonyOS 4已经于2023年8月4日在HDC2023大会上正式官宣。对广大HarmonyOS开发者而言&#xff0c;这次一次盛大的大会。截至目前&#xff0c;鸿蒙生态设备已达7亿台&#xff0c;HarmonyOS开发者人数超过220万。鸿蒙生态充满着新机遇&#xff0c;也必将带来新的挑战。 HarmonyO…

卷积神经网络实现MNIST手写数字识别 - P1

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;365天深度学习训练营-第P1周&#xff1a;实现mnist手写数字识别&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同…

架构训练营学习笔记:5-3接口高可用

序 架构决定系统质量上限&#xff0c;代码决定系统质量下限&#xff0c;本节课串一下常见应对措施的框架&#xff0c;细节不太多&#xff0c;侧重对于技术本质有深入了解。 接口高可用整体框架 雪崩效应&#xff1a;请求量超过系统处理能力后导致系统性能螺旋快速下降 链式…

mssqlmysql数据库忽略大小写

一、mssql -- 创建数据时指定排序集Latin1_General_CI_AS CREATE DATABASE [数据库名] COLLATE Latin1_General_CI_AS 查询效果&#xff1a; 二、mysql

课程作业-基于Python实现的迷宫搜索游戏附源码

简单介绍一下 该项目不过是一个平平无奇的小作业&#xff0c;基于python3.8开发&#xff0c;目前提供两种迷宫生成算法与三种迷宫求解算法&#xff0c;希望对大家的学习有所帮助。 项目如果有后续的跟进将会声明&#xff0c;目前就这样吧~ 效果图如下所示&#xff1a; 环境…

AP2400 LED汽车摩灯照明电源驱动 过EMC DC-DC降压恒流IC

产品特点 宽输入电压范围&#xff1a;5V&#xff5e;100V 可设定电流范围&#xff1a;10mA&#xff5e;6000mA 固定工作频率&#xff1a;150KHZ 内置抖频电路&#xff0c;降低对其他设备的 EMI干扰 平均电流模式采样&#xff0c;恒流精度更高 0-100%占空比控制&#xff0…

基于Pyqt5+serial的串口电池监测工具

本章&#xff0c;其他的没有&#xff0c;废话没有&#xff0c;介绍一下新开源了一个公司的测试工具&#xff0c;写了差不多三周吧。先来看看界面&#xff1a; 这是一个串口调试界面&#xff0c;使用Pyqt5serial完成。升级功能暂未移入&#xff0c;占一个坑位。 基于serial二次开…

javaAPI(一):String

String的特性 String底层源码 1、String声明为final&#xff0c;不可被继承 2、String实现了Serializable接口&#xff1a;表示字符支持序列化 实现了Comparable接口&#xff1a;表示String可以比较大小 3、String内部定义了final char[] value用于存储字符串 4、通过字面量的…

20天突破英语四级高频词汇——第①天

2&#xfeff;0天突破英语四级高频词汇~第一天加油(ง •_•)ง&#x1f4aa; &#x1f433;博主&#xff1a;命运之光 &#x1f308;专栏&#xff1a;英语四级高频词汇速记 &#x1f30c;博主的其他文章&#xff1a;点击进入博主的主页 目录 2&#xfeff;0天突破英语四级…

CSS基础介绍笔记1

官方文档 CSS指的是层叠样式&#xff08;Cascading Style Sheets&#xff09;地址&#xff1a;CSS 教程离线文档&#xff1a;放大放小&#xff1a;ctrl鼠标滚动为什么需要css&#xff1a;简化修改HTML元素的样式&#xff1b;将html页面的内容与样式分离提高web开发的工作效率&…

windows开机运行jar

windows开机自启动jar包&#xff1a; 一、保存bat批处理文件 echo off %1 mshta vbscript:CreateObject("WScript.Shell").Run("%~s0 ::",0,FALSE)(window.close)&&exit java -jar E:\projects\ruoyi-admin.jar > E:\server.log 2>&1 &…

自监督去噪:Neighbor2Neighbor原理分析与总结

文章目录 1. 方法原理1.1 先前方法总结1.2 Noise2Noise回顾1.3 从Noise2Noise到Neighbor2Neighbor1.4 框架结构2. 实验结果3. 总结 文章链接&#xff1a;https://arxiv.org/abs/2101.02824 参考博客&#xff1a;https://arxiv.org/abs/2101.02824 1. 方法原理 1.1 先前方法总…

C数据结构与算法——哈希表/散列表创建过程中的冲突与聚集(哈希查找) 应用

实验任务 (1) 掌握散列算法&#xff08;散列函数、散列存储、散列查找&#xff09;的实现&#xff1b; (2) 掌握常用的冲突解决方法。 实验内容 (1) 选散列函数 H(key) key % p&#xff0c;取散列表长 m 为 10000&#xff0c;p 取小于 m 的最大素数&#xff1b; (2) 测试 α…