java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot整合SpringSecurity

基于数据库的用户认证实现SpringBoot3整合SpringSecurity6的过程

作者:程序员晓凡

这篇文章主要介绍了基于数据库的用户认证实现SpringBoot3整合SpringSecurity6的过程,本文通过实例图文并茂的形式给大家介绍的非常详细,感兴趣的朋友一起看看吧

写在前面

上一篇文章中,我们了解了SpringSecurity怎么基于内存进行用户认证。但这还远远不够,在实际开发中。

用户往往都存在于数据库,所以从这篇文章开始,我们就要开始学习基于数据库的用户认证。

一、认证流程

其实基于数据库的用户认证和基于内存认证大同小异,我们只需要将从内存获取用户信息,换成从数据库获取用户信息即可。

换成代码就是替换掉InMermoryUserDetailManager 实现类,自己去实现UserDetailsService,从数据库查询用户然后返回。

二、SpringBoot3整合数据库

在进行认证前,我们需要保证SpringBoot能正常整合数据库,查询用户信息。这里我们使用的数据库是MySQL8.0

2.1 创建数据库、表、插入数据

①创建数据库

我们这里创建一个security-demo的数据库

-- 创建数据库
CREATE DATABASE `security-demo`;
USE `security-demo`;

② 创建用户

-- 创建用户表
CREATE TABLE `user`(
	`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,  -- 主键ID
	`username` VARCHAR(50) DEFAULT NULL ,  -- 用户名
	`password` VARCHAR(500) DEFAULT NULL, -- 密码
	`enabled` BOOLEAN NOT NULL -- 是否启用
);

③ 创建唯一索引

在这里一个用户的用户名username字段肯定是不能重复的,所以要为username创建唯一索引,保证username的唯一

CREATE UNIQUE INDEX `user_username_uindex` ON `user`(`username`); 

④ 插入数据

为了方便测试,我们默认插入几个用户。为了安全起见,这里密码采用SpringSecurity默认的bcrypt加密方式。不清楚的小伙可以先不用管,再后面的文章中会详细介绍到密码加密算法

-- 插入用户数据(密码是 "password" )
INSERT INTO `user` (`username`, `password`, `enabled`) VALUES
('admin', '{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW', TRUE),
('xiezhr', '{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW', TRUE),
('xiaofan', '{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW', TRUE);

2.2 配置Lombok

为了偷懒,我们还引入了Lombok。 使用Lombok,可以让我们避免写getsettoString等样板式代码。堪称偷懒神器,解放了双手。

① 下面例举了怎么使用Lombok 来偷懒

② IDEA 中安装 Lombok 插件

我们需要再IDEA中安装了Lombok插件,才能正式愉快的使用Lombok

根据你的系统依次点击菜单:

Mac 系统:IntelliJ IDEA -> Preferences -> Plugins;

点击 Marketplace , 进入插件市场, 输入关键词 lombok, 搜索该插件:

③ 引入依赖

在pom.xml文件中添加如下依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.32</version>
</dependency>

2.3 引入Mybatis Plus

为了方便后续数据库增删改查等操作,我们引入MybatisPuls作为持久层框架。

① Mybatis Plus简介

有些小伙伴可能还不知道MybatisPuls,这里简单介绍一下,知道的小伙伴直接跳过即可。

用白话文说MybatisPuls是一款操作数据库的框架。它是一个 MyBatis 的增强工具,就像 iPhone手机一般都有个 plus 版本一样,它在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

MyBatis Plus 的愿景是成为 MyBatis 最好的搭档,就像魂斗罗中的 1P2P,基友搭配,效率翻倍。

② 引入依赖

为了整合mybatis-plus,我们需要在pom.xml中引入如下依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    <version>3.5.5</version>
</dependency>

2.4 引入MySQL依赖

我们这里数据库使用的是MySQL,所以还得引入MySQL相关依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>

2.5 完整依赖

最终完整依赖如下

<dependencies>
    <!-- web依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--SpringSecurity 依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
        <version>3.2.10</version>
    </dependency>
    <!--lombok依赖-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.32</version>
    </dependency>
    <!--SpringBoot3整合mybatis-plus 依赖-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
        <version>3.5.5</version>
    </dependency>
    <!--junit依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!--MySQL依赖-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
</dependencies>

2.6 配置数据源

application.yml文件中配置MySQL数据源,即mybatis-plus日志

# MySQL数据源
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3308/security-demo
    username: root
    password: 123456
# MySQL日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

2.7 创建实体类

package com.xiezhr.securityindbuser.entity;
@TableName("user")
@Data
public class User {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    @TableField(value = "username")
    private String username;
    @TableField(value = "password")
    private String password;
    @TableField(value = "enabled")
    private Boolean enabled;
}

2.8 Mapper接口

package com.xiezhr.securityindbuser.mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

2.9 Service

① 接口

package com.xiezhr.securityindbuser.service;
public interface UserService extends IService<User> {
}

② 实现

package com.xiezhr.securityindbuser.service.impl;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

2.10 Controller

package com.xiezhr.securityindbuser.controller;
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/list")
    public List<User> getUserList(){
        return userService.list();
    }
}

2.11 测试是否正常获取数据

以上小节中,我们建立了各种类。结构如下

启动服务,浏览器中输入:http://localhost:8080/user/list 看看是否能查出数据库中用户数据?

至此,我们已经成功整合数据库,并且从数据库中查询出了用户信息。

接下来,我们要做的就是把认证流程从内存中获取用户信息替换成我们自己实现从数据库中查询用户信息。

三、基于数据库的用户认证

3.1 认证流程

通过之前基于内存认证分析,我们知道。只要实现UserDetailsService 接口的loadUserByUsername 方法就可以从数据库中获取用户信息。

3.2 创建DBUserDetailsManager

我们在service包下创建DBUserDetailsManager 来实现UserDetailsService 接口,替换从内存中获取用户信息。代码如下

package com.xiezhr.securityindbuser.service.impl;
public class DBUserDetailsManager implements UserDetailsService {
    @Resource
    private UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        //使用username构造查询条件
        QueryWrapper<User> wrapper = queryWrapper.eq("username", username);
		//由于用户名不能重复,所以我们使用selectOne查询用户信息即可
        User user = userMapper.selectOne(wrapper);
        if (user == null) {
            //用户不存在,抛出异常
            throw new UsernameNotFoundException(username);
        } else {
            //由于现在还没有权限信息,所以我们构造一个空的权限信息
            Collection< GrantedAuthority> authorities = new ArrayList<>();
            return new org.springframework.security.core.userdetails.User(
                    user.getUsername(),  //
                    user.getPassword(),
                    user.getEnabled(),
                    true,  //用户账户是否没过期
                    true, //用户凭证是否没过期
                    true, //用户是否未被锁定
                    authorities //用户权限信息
            );
        }
    }
}

3.3 初始化UserDetailsService

说了一堆理论,那么我们怎么才能让springsecurity不从内存获取用户信息,而是通过上一步创建的DBUserDetailsManager 来查询用户信息。

接下来的就比较关键了,我们只需创建一个WebSecurityConfig,然后创建基于数据库的用户管理器dbUserDetailsManager即可

package com.xiezhr.securityindbuser.config;
@Configuration  //标明这个类为配置类,spring应用程序一启动,类中的been 就会被初始化在spring容器中
@EnableWebSecurity  //开启spring security 自定义配置
public class WebSecurityConfig {
    @Bean
    public UserDetailsService userDetailsService(){
        //创建基于数据库的用户管理器
        DBUserDetailsManager dbUserDetailsManager = new DBUserDetailsManager();
        return dbUserDetailsManager;
    }
}

当然我们也可以直接在DBUserDetailsManager类上添加@Component注解,也能实现同样的效果

3.4 测试一下

通过上面的步骤,基于数据库的认证基本就完成了。

在整合数据库的时候我们插入了三个用户信息

下面我们来测试下成果,浏览器中输入:http://localhost:8080/user/list

随便输入上面三个用户中一个,admin/password xiezhr/password xiaofan/password 即可正常访问接口

到此,我们成功完成了基于数据库的用户认证功能,是不是很简单呢~

到此这篇关于SpringBoot3整合SpringSecurity6(三)基于数据库的用户认证的文章就介绍到这了,更多相关SpringBoot3整合SpringSecurity6(三)基于数据库的用户认证内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文