spring boot(学习笔记第十四课)
- Spring Security的密码加密,基于数据库认证
学习内容:
- Spring Security的密码加密
- 基于数据库认证
1. Spring Security的密码加密
- 如果用户的密码保存在数据库中是以明文保存,对于公司的安全将是灾难性的,哪个公司也不会允许用户数据使用明文保存。这里练习使用加密之后的密码进行认证。
注意,这样公司的数据库里面是没有用户的明文密码,即使数据库泄露,也不会暴漏用户的明文密码 - 实现密码加密
- 配置
passwordEncoder
@Bean PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(10); }
- 手动根据明文密码生成密文密码
bcrypt转换工具
注意,每次生成的密码都不一样,但是每个生成的都好用
- 使用生成的密文进行用户的创建。
@BeanUserDetailsService userDetailsService() {InMemoryUserDetailsManager users =new InMemoryUserDetailsManager();users.createUser(User.withUsername("finlay_user").password("$2a$10$uwwZ5EyWbFnnw3JG53rqQ.VJUm/.Pl9Ko1CUP5Aqc2kuBr2Bx7bc.").roles("USER").build());
- 再次进行认证。
- 配置
2. 基于数据库认证
以上练习了基于内存的认证,实际上,正式的系统开发都是使用数据库进行认证,在这里练习使用使用数据库的用户数据进行认证。这里使用postgresql
。
- 首先创建数据库需要的表
- 创建
USER
表CREATE TABLE "USER"( id int, username varchar(32), password varchar(255), enabled int, locked int, PRIMARY KEY(id) );
- 创建
ROLE
表CREATE TABLE "ROLE"( id int, name varchar(32), nameZh varchar(255), PRIMARY KEY(id) );
- 创建
USER_ROLE
表(user
和role
的关系表)CREATE TABLE "USER_ROLE"( id int, uid int, rid int, PRIMARY KEY(id) );
- 用户数据如下:
USER
表
ROLE
表
USER_ROLE
表
USER
和ROLE
的关系with uur as ( select* from"USER" u inner join "USER_ROLE" ur on u.id = ur.uid)select username,namezh,name as rolename from uur inner join "ROLE" r on uur.rid = r.id
- 创建
- 引入必要的依赖
这里<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>3.0.3</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><scope>runtime</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.9</version></dependency>
repository
使用mybatis
,所以引入mybatis
的依赖包。 - 在
application.properties
定义数据库连接信息。spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/springboot spring.datasource.username=finlay spring.datasource.password=123456
- 定义
mybatis
的interface
,以及xml
文件- 定义
User
和Role
的实体类@Data public class Role {private Integer id;private String name;private String nameZh; }
@Data public class User implements UserDetails {private Integer id;private String username;private String password;private Boolean enabled;private Boolean locked;private List<Role> roles;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {List<SimpleGrantedAuthority> authorities = new ArrayList<>();for (Role role : roles) {authorities.add(new SimpleGrantedAuthority(role.getName()));}return authorities;}@Overridepublic String getPassword() {return this.password;}@Overridepublic String getUsername() {return this.username;}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return !this.locked;}@Overridepublic boolean isCredentialsNonExpired(){return true;}@Overridepublic boolean isEnabled(){return this.enabled;} }
- 配置
mybatis
@Mapper public interface UserMapper {User loadUserByUserName(String usernam);List<Role> getUserRolesByUid(Integer id); }
- 配置
mybatis
的xml
配置文件<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.repository.mybatis.UserMapper"><select id="loadUserByUserName" resultType="com.example.demo.authentication.User">select * from "USER" where username=#{username}</select><select id="getUserRolesByUid" resultType="com.example.demo.authentication.Role">select * from "ROLE" r, "USER_ROLE" ur where r.id=ur.rid and ur.uid=#{id}</select> </mapper>
- 定义
- 定义
UserDetailsService
注意,这里生成了@Service public class UserService implements UserDetailsService {@Autowiredpublic UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userMapper.loadUserByUserName(username);if (user == null) {throw new UsernameNotFoundException("username is not found");}user.setRoles(userMapper.getUserRolesByUid(user.getId()));return user;} }
UserDetailsService
的bean
,所以spring boot security的
的认证处理,都会使用这个bean
- 整体的架构
- 测试认证结果