说明
(1)JDK版本:1.8
(2)Spring Boot 2.0.6
(3)Spring Security 5.0.9
(4)Spring Data JPA 2.0.11.RELEASE
(5)hibernate5.2.17.Final
(6)MySQLDriver 5.1.47
(7)MySQL 8.0.12
需求缘起
在前面使用的是内存数据库,本节使用MySQL数据库进行操作。
编码思路
在《基于内存数据库的身份认证和角色授权》的代码转换为MySQL数据库的存储方式的话,非常的简单,只需要添加MySQL数据库的驱动包以及配置好数据源和JPA。
一、基于MySQL数据库的身份认证和角色授权
1.1 添加依赖
在pom.xml文件中去掉hsqldb的依赖,然后添加mysql的依赖:
mysql
mysql-connector-java
1.2 添加配置信息
在application.properties文件中添加配置信息:
spring.datasource.url = jdbc:mysql://localhost:3306/spring-security
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driverClassName = com.mysql.jdbc.Driver
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = create-drop
1.3 启动测试
启动应用程序,成功的话可以看到数据库的数据:
按照之前的流程测试下,结果是一样的。到这里的话,我并没有做过多的编码,那么这么轻松从内存数据库转换到MySQL数据库,这就是框架给我们提供的便利。
二、数据库密码加密保存
到这里基本的流程都是没有问题的,但是我们发现数据库的密码都是明文显示的,这个就要命了,那么数据库的密码怎么加密保存呢?其实也很简单,在初始化用户信息的时候,就进行加密就可以了,具体的操作如下:
2.1 修改DataInit
修改DataInit类,注入PasswordEncoder,使用PasswordEncoder的encode方法对密码进行加密:
package com.kfit.permission.init;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.kfit.permission.bean.UserInfo;
import com.kfit.permission.bean.UserInfo.Role;
import com.kfit.permission.repository.UserInfoRepository;
@Service
public class DataInit {
@Autowired
private UserInfoRepository userInfoRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@PostConstruct
public void dataInit() {
UserInfo admin = new UserInfo();
admin.setUsername("admin");
admin.setPassword(passwordEncoder.encode("123"));
admin.setRole(Role.admin);
userInfoRepository.save(admin);
UserInfo user = new UserInfo();
user.setUsername("user");
user.setPassword(passwordEncoder.encode("123"));
user.setRole(Role.normal);
userInfoRepository.save(user);
}
}
2.2 修改CustomUserDetailService
在添加用户的时候,已经加密了,那么在loadUserByUsername方法中返回的UserDetails就不需要再加密了,修改为如下:
package com.kfit.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
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.kfit.permission.bean.UserInfo;
import com.kfit.permission.service.UserInfoService;
@Component
public class CustomUserDetailService implements UserDetailsService{
@Autowired
private UserInfoService userInfoService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("CustomUserDetailService.loadUserByUsername()");
//通过username获取用户信息
UserInfo userInfo = userInfoService.findByUsername(username);
if(userInfo == null) {
throw new UsernameNotFoundException("not found");
}
//定义权限列表.
List authorities = new ArrayList<>();
// 用户可以访问的资源名称(或者说用户所拥有的权限) 注意:必须"ROLE_"开头
authorities.add(new SimpleGrantedAuthority("ROLE_"+userInfo.getRole().name()));
User userDetails = new User(userInfo.getUsername(),userInfo.getPassword(),authorities);
return userDetails;
}
}
2.3 启动测试
启动应用,查看数据库的用户信息:
此时看到的密码已经是加密的了,访问下如下的地址:
http://127.0.0.1:8080/hello/helloUser
输入账号user/123看是否可以正常登录吧。
三、其他
3.1 Mac下安装MySQL
在Mac下安装MySQL常用的有两种方式,第一种方式就是下载官网的dmg文件,直接进行安装;第二种方式,就是命令方式,这里使用的是brew命令。
3.1.1 安装brew
由于使用的是brew install mysql安装的mysql,所以需要先安装brew,安装指令如下:
$ruby -e "$(curl -fsSLhttps://raw.githubusercontent.com/Homebrew/install/master/install)"
3.1.2 安装mysql
已经安装神奇brew的话,那么安装mysql就很简单了,安装指令如下:
$ brew install mysql
3.1.2 mysql启动指令
Mysql启动指令:
$ mysql.server start
3.2 navicat连接MySQL8+时出现2059错误解决方法
3.2.1 原因分析
安装完数据库,使用select version()数据库版本是8.0.12的,在用navicat连接MySQL8+时会出现2059错误,,这是由于新版本的MySQL使用的是caching_sha2_password验证方式,但此时的navicat还没有支持这种验证方式。
3.2.2 解决方法
解决方法就是将验证方式改为以前版本(5.7及以下)使用的验证方式mysql_native_password。具体的验证方式可以查看默认数据库'mysql'中user表plugin字段。
在命令行中登录数据库时不会出现2059错误,在命令行中登录数据库,执行下面的命令:
$ ALTER USER 'root'@'localhost' IDENTIFIED WITHmysql_native_password BY 'password';
'password'是你想使用的验证密码。
3.2.2 解决方法二
另外一种方法就是升级navicat到最新版本,最新版本已经支持新的密码验证方式了。