Spring Security学习——使用数据库保存密码
Posted sadoshi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Security学习——使用数据库保存密码相关的知识,希望对你有一定的参考价值。
前言
上一篇文章我们已经快速搭起Spring Security应用。我们使用的是默认的用户名密码。通常项目中我们使用数据库保存密码,并且数据库的密码是加密保存的。如何做到呢,是这篇文章的重点。
引入数据库
新建数据库表
我们新建数据库“spring_security_test”,然后再里面新建一个简单的用户表,这个表非常简单,只有用户名和密码字段:
CREATE TABLE `sys_user` (
`id` int(11) NOT NULL,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;
引入mybatis-plus
为了方便数据库操作,这里使用mybatis-plus。当然如果读者喜欢使用mybatis或者单纯使用jdbc连接也可以,自行实现即可。
首先引入pom依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
接着配置mybatis-plus的配置项,在application.yml中添加配置:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
url: jdbc:mysql://127.0.0.1:3306/spring_security_test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password:
创建用户表实体SysUserEntity:
package com.sadoshi.springsecurity.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("sys_user")
public class SysUserEntity
private Long id;
private String username;
private String password;
新建DAO接口SysUserMapper:
package com.sadoshi.springsecurity.dao;
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sadoshi.springsecurity.domain.entity.SysUserEntity;
@Mapper
public interface SysUserMapper extends BaseMapper<SysUserEntity>
新建Service层接口SysUserService和其实现类SysUserServiceImpl:
package com.sadoshi.springsecurity.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sadoshi.springsecurity.domain.entity.SysUserEntity;
public interface SysUserService extends IService<SysUserEntity>
package com.sadoshi.springsecurity.service.impl;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sadoshi.springsecurity.dao.SysUserMapper;
import com.sadoshi.springsecurity.domain.entity.SysUserEntity;
import com.sadoshi.springsecurity.service.SysUserService;
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements SysUserService
至此引入完毕。
实现Spring Security读取用户名密码接口
前面我们已经准备好了用户名密码表,也实现了相应的数据库接口,接下来要做的事就是让Spring Security读取用户名密码,让其在内部比对用户名密码是否匹配。
实现UserDetails接口
UserDetails是Spring Security用户接口类,我们要实现这个接口类,用于返回各类用户名、密码、权限等。可以理解为这就是Spring Security内部的用户信息实体。创建LoginUser类实现该接口:
package com.sadoshi.springsecurity.domain.model;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.sadoshi.springsecurity.domain.entity.SysUserEntity;
public class LoginUser implements UserDetails
private SysUserEntity user;
public LoginUser(SysUserEntity user)
this.user = user;
@Override
public Collection<? extends GrantedAuthority> getAuthorities()
return null;
@Override
public String getPassword()
return user.getPassword();
@Override
public String getUsername()
return user.getUsername();
@Override
public boolean isAccountNonExpired()
return true;
@Override
public boolean isAccountNonLocked()
return true;
@Override
public boolean isCredentialsNonExpired()
return true;
@Override
public boolean isEnabled()
return true;
由于权限、用户是否锁定等信息目前我们还用不上,因此先简单配置,以确保我们测试正常。
实现UserDetailsService接口
我们还要实现一个接口,当Spring Security需要进行比对的时候,如何读取相关的用户信息,并返回一个用户信息的实体类给Spring Security,需要在这个接口中实现。我们新建UserDetailsServiceImpl类实现UserDetailsService接口:
package com.sadoshi.springsecurity.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sadoshi.springsecurity.domain.entity.SysUserEntity;
import com.sadoshi.springsecurity.domain.model.LoginUser;
import com.sadoshi.springsecurity.service.SysUserService;
@Component
public class UserDetailsServiceImpl implements UserDetailsService
@Autowired
private SysUserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<SysUserEntity>();
queryWrapper.eq("username", username);
queryWrapper.last("limit 1");
SysUserEntity user = userService.getOne(queryWrapper);
if(user == null)
throw new RuntimeException("No user named " + username);
return (new LoginUser(user));
查看Spring Security源码可知,Spring Security进行认证时会调用loadUserByUsername获取用户信息,因此我们实现这个方法,并返回我们LoginUser的实例。
验证
我们在数据库表sys_user新增一条记录:
然后运行项目,并在浏览器输入http://localhost:8082/hello,跳转到登录页后,输入帐号jake,密码123。便可以登入。
密码的前缀
读者会注意到,密码项有个noop的前缀。前缀的作用是表示其加密的方式,noop表示没有加密。后面文章可以专门研究一下Spring Security的加密方式
小结
本文讲述如何使用数据库保存用户名密码,Spring Security如何读取这些信息。同时也展示了如何整合mybatis-plus到项目中。后面还提出了关于密码加密的疑问,留待后面文章学习。
以上是关于Spring Security学习——使用数据库保存密码的主要内容,如果未能解决你的问题,请参考以下文章