首页 > 数据库 >Spring Security系列教程09--基于默认数据库模型实现授权

Spring Security系列教程09--基于默认数据库模型实现授权

时间:2022-12-23 15:04:45浏览次数:43  
标签:users -- Spring 数据库 09 用户 JdbcUserDetailsManager 创建 我们


前言

在上一个章节中,一一哥 给大家讲解了如何基于内存模型来实现授权,在这种模型里,用户的信息是保存在内存中的。你知道,保存在内存中的信息,是无法持久化的,也就是程序一旦关闭,或者断电等情况发生,内存中的信息就丢失了,所以这种方式并不适用于生产环境!

那么我们肯定要把用户信息持久化, 但是持久化到哪里去呢?那就是数据库呗!数据库是我们做程序员必会必熟的知识点,尤其是做后端开发,开发时常用的数据库有MySQL和Oracle,本案例中我们采用的是MySQL数据库。

一. JdbcUserDetailsManager类介绍

在进行编码实现之前,壹哥 先和各位一起来看看Spring Security给我们提供的持久化API都有哪些,以及这些API之间的关系结构。

1. UserDetailsService接口

Spring Security 支持MySQL、Oracle等多种不同的数据源,这些不同的数据源最终都由 UserDetailsService 这个接口的子类来负责进行操作,我们先来看看 UserDetailsService 接口都有哪些实现类:

Spring Security系列教程09--基于默认数据库模型实现授权_bc

2. JdbcUserDetailsManager实现类

在上一章节中,我给大家介绍了如何在内存中创建并保存用户及角色信息,这种实现方式主要是利用InMemoryUserDetailsManager这个子类来实现的。如果我们想在数据库中创建并保存用户及角色信息,Spring Security也很贴心,它还给我们提供了另一个UserDetailsService的实现子类,也就是JdbcUserDetailsManager。其中JdbcUserDetailsManager类的关系结构如下图所示:

Spring Security系列教程09--基于默认数据库模型实现授权_bc_02

从上图中,我们可以看到JdbcUserDetailsManager的直接父类是JDBCDaoSuport,利用JdbcUserDetailsManager可以帮助我们以JDBC的方式对接数据库进行增删改查等操作。它内部设定了一个默认的数据库模型,只要遵从这个模型,我们就可以很方便的实现在数据库中创建用户名和密码、角色等信息,但是灵活性不足。

二. 项目实现

了解完上面的相关API之后,咱们闲言少叙,直接动起手来撸码吧。

1. 准备测试接口

接下来我们就在上一章节创建的项目基础之上,创建一个新的model,并对项目进行改造。我们还是跟之前一样,先创建3个测试接口,具体过程请参考之前章节。

2. 准备数据库

既然我们要操作数据库,那肯定得先建库建表啊,那么数据库和表结构是什么样呢?我们怎么创建出来呢?其实JdbcUserDetailsManager本身就给我们提供了对应的数据库脚本模型,这个数据库脚本模型保存在如下位置:

org/springframework/security/core/userdetails/jdbc/users.ddl

Spring Security系列教程09--基于默认数据库模型实现授权_数据库_03

所以我们直接去这个对应的位置下,找到这个数据库脚本文件打开即可。

3. users数据库脚本

当我们打开这个users.ddl文件,可以看到如下内容,会发现其中有2个建表语句,分别是创建了users表和authorities表,并且在authorities表中创建了唯一索引。

create table users(username varchar_ignorecase(50) not null primary key,password varchar_ignorecase(500) not null,enabled boolean not null);

create table authorities (username varchar_ignorecase(50) not null,authority varchar_ignorecase(50) not null,constraint fk_authorities_users foreign key(username) references users(username));

create unique index ix_auth_username on authorities (username,authority);

这时候我们只需要先自己创建一个数据库,编码格式就采用UTF-8,然后把上面的建表语句,复制粘贴并执行,创建出2个表即可。users表用来存放用户名、用户密码以及账户是否可用,authorities表用来存放用户名及其对应权限,authorities 和 users 会通过 username 字段关联起来。

如下图所示:

Spring Security系列教程09--基于默认数据库模型实现授权_mysql_04

注意:

上面的建表脚本中,有一种数据类型 varchar_ignorecase,这个是针对 HSQLDB 数据库创建的,但是我们使用的 MySQL 数据库并不支持这种数据类型,所以这里需要我们手动将这个数据类型改为 varchar。

4. 添加数据库依赖

接下来我们在pom.xml文件中,除了已有的spring-web和spring-security的依赖之外,还要再新增关于数据库的依赖包。

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

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

<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

5. 添加数据库配置文件

添加完依赖包之后,我们在resource目录下创建一个application.yml文件,并在其中添加关于数据库的配置信息。

spring:
datasource:
url: jdbc:mysql://localhost:3306/db-security02?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
username: root
password: syc

注意:

url中数据库的名字,需要改成自己的数据库名称,用户名和密码也要改成自己mysql的用户信息。

6. 编写编码类

然后我们编写一个SecurityConfig类,在其中配置对资源的访问控制,创建一个UserDetailsService实例,并在其中配置,生成存储用户和角色信息

@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

/***************************************在默认的数据库中创建用户和角色****************************************************/

@Autowired
private DataSource dataSource;

@Bean
public UserDetailsService createUserDetailService() {
JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
manager.setDataSource(dataSource);

if (!manager.userExists("user")) {
manager.createUser(User.withUsername("user").password("123").roles("USER").build());
}

if (!manager.userExists("admin")) {
manager.createUser(User.withUsername("admin").password("123").roles("USER", "ADMIN").build());
}

return manager;
}

@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}

}

因为我们利用的是SpringBoot环境,只要我们配置好了数据库依赖和环境,就可以直接在这个SecurityConfig配置类中引用DataSource对象。

7. 核心代码释义

对上面SpringSecurity类中的代码,我主要针对createUserDetailService()方法进行解释。

  • 在这个方法中,我们首先构建一个 JdbcUserDetailsManager 实例对象,并给 JdbcUserDetailsManager 实例添加一个 DataSource 对象。
  • 接下来调用 userExists()方法 判断用户是否存在,如果不存在,就创建一个新的用户出来(因为每次项目启动时这段代码都会执行,所以加一个判断,避免重复创建用户)。
  • 用户的创建方法和我们之前 InMemoryUserDetailsManager 中的创建用户的方法基本一致。

以上就是我们基于默认的数据库模型实现的对用户及角色的操作,之所以可以实现,就是因为在UserDetailsManager这个父接口中,定义了如下方法,这些方法在子类中都有具体的实现。

Spring Security系列教程09--基于默认数据库模型实现授权_数据库_05

我们可以看到UserDetailsManager类中,提供了创建、修改、删除、判断用户是否存在的方法,和修改用户密码的方法。

在JdbcUserDetailsManager这个实现子类中,已经定义好了users与authorities表对应的CRUD语句,所以我们直接调用相关方法即可实现对用户及角色的管理。另外我们在特殊情况下,也可以自定义这些SQL语句,如有需要,调用对应的setXxxSQL()方法即可。

Spring Security系列教程09--基于默认数据库模型实现授权_java_06

8. 项目结构

以上案例的完整代码结构如下图所示,请参考创建。

Spring Security系列教程09--基于默认数据库模型实现授权_数据库_07

三. 测试运行

1. 启动项目测试

接下来我们把项目启动起来进行测试,这时候效果跟基于内存模型的授权实现效果是一样的,具体测试界面 壹哥 这里就不再展示了。

2. 小结

当我们使用Spring Security默认的数据库模型来操作实现用户授权时,存在灵活性不足的问题,因为我们必须按照源码规定的方式去建库建表。而我们真正开发时,用户角色等表肯定是根据自己的项目需求来单独设计的,所以真正开发时,我们有必要进行用户及角色表的自定义设计。

接下来 壹哥 就会带各位学习更灵活的基于自定义数据库模型的开发实现方式,敬请期待哦。对于本篇不明白的地方,请在评论区留言!

标签:users,--,Spring,数据库,09,用户,JdbcUserDetailsManager,创建,我们
From: https://blog.51cto.com/u_7044146/5965733

相关文章

  • Spring Security系列教程08--基于内存模型实现授权
    前言在前面的几个章节中,一一哥带大家学会了如何创建SpringSecurity项目,3种认证方式,以及在前后端分离时的安全处理方案。在之前的这几章节中,我们主要学习的还是关于"认证"......
  • 肯天脱模剂 | 浪漫的节日需要礼物,包装需要肯天螺杆清洗剂助力
    昨天是七夕情人节,都说玫瑰与你皆是浪漫,爱你的心何止“七夕”,更是“朝朝夕夕”。向心爱的他表达爱意时,当然少不了礼物。不论是巧克力还是化妆品,这些用精美包装盒包装的礼物在......
  • 皕杰报表小结
    1.在使用皕杰报表时,我们会发现皕杰报表总共有下列五个视图区 我们可以关闭或打开每个视图区,方便我们的报表设计。有的时候我们关闭了某个视图的话,我们可以通过点击左上角的......
  • SpringBoot2.x系列教程04--新纪元之SpringBoot环境要求
    SpringBoot系列教程04--新纪元之SpringBoot环境要求作者:一一哥一.基本说明本系列教程采用SpringBoot2.x.x.RELEASE版本;需要Java8+版本;SpringFramework5.0.4.RELEASE......
  • SpringBoot2.x系列教程19--Web开发05之XML方式实现SSM整合
    SpringBoot系列教程19--Web开发05之XML方式实现SSM整合作者:一一哥注意:本系列教程案例继续在之前的基础上进行编写!SpringBoot可以帮助我们快速搭建一个SSM框架环境,那么该怎......
  • SpringBoot2.x系列教程18--Web开发04之实现文件上传
    SpringBoot系列教程18--Web开发04之实现文件上传作者:一一哥一.概述文件上传是开发中比较常见的功能之一.但是SpringBoot并没有提供特别的文件上传技术,而是依赖于SpringMVC......
  • SpringBoot2.x系列教程17--Web开发03之支持jsp
    SpringBoot系列教程17--Web开发03之支持jsp作者:一一哥咱们都知道,在SpringMVC中是支持JSP的,但是在SpringBoot中,其实不建议使用JSP。因为在使用嵌入式servlet容器时,有一些......
  • 教你用JavaScript实现计数器
    案例介绍欢迎来到我的小院,我是霍大侠,恭喜你今天又要进步一点点了!我们来用JavaScript编程实战案例,做一个计数器。点击按钮数字改变,点击重置数字归0。通过实战我们将学......
  • 教你用JavaScript实现计数器
    案例介绍欢迎来到我的小院,我是霍大侠,恭喜你今天又要进步一点点了!我们来用JavaScript编程实战案例,做一个计数器。点击按钮数字改变,点击重置数字归0。通过实战我们将学会fo......
  • 数字化工厂对比传统工厂有哪些好处
    在工业4.0的背景下,向数字化工厂转型是传统工厂转型的趋势。很多企业领导还在疑惑,数字化工厂比传统工厂有哪些优势呢?针对传统工厂,数字化工厂将设备联网,数据自动反馈,更好的去......