文末有本篇文章的项目源码文件可供下载学习
通过SpringSecurity快速入门案例我们已经实现了基于内存的校验用户信息,但在实际项目中我们需要校验从数据库中获取的用户信息,这里我们主要是两步操作:
1.需要我们实现UserDetailsService的loadUserByUsername方法,在方法中以前端传入的username为条件,看是否能在数据库中查询到User,如果能够查到,将查到的User信息(重要的是密码信息和授权信息)存放到UserDetails对象中.
2.通过密码加密器BCryptPasswordEncoder将前端传入的username进行加密,将加密之后的字符串与数据库中的password字段信息进行校验.在SpringSecurity中我们不需要编写校验代码,只需将BCryptPasswordEncoder放入到SpringIoC容器即可,
0.配置思路
- 搭建项目,配置pom.xml,引入相关依赖.
- 新建UserDetailsImpl,实现UserDetails的相关方法.
- 配置数据库/Mybatis等信息.
- 新建UserMapper.java/UserMapper.xml/CustomerController.java文件
- 新建UserDetailsServiceImpl.java,实现UserDetailsService的loadUserByUsername方法.
- 新建SecurityConfig.java,配置好密码加密器BCryptPasswordEncoder.
- 测试1:对BCryptPasswordEncoder进行测试,得到加密密码,手动存入数据库中.
- 测试2.启动SpringBoot,测试是否能够进行数据库用户信息的校验,完成登录操作.
1.配置pom.xml文件
<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>
</dependency>
<!-- mybatis启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version> <!-- 请检查最新版本 -->
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.新建UserDetailsImpl.java
public class UserDetailsImpl implements UserDetails {
private User user;
public UserDetailsImpl(User user) {
this.user = user;
}
/**
* 获取权限信息
* @return
*/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
/**
* 获取密码信息
* @return
*/
@Override
public String getPassword() {
return this.user.getPassword();
}
/**
* 获取用户名信息
* @return
*/
@Override
public String getUsername() {
return this.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;
}
}
3.配置数据库/Mybatis等信息
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mytest?characterEncoding=utf-8&serverTimezone=UTC
username: root
password: root
mybatis:
configuration: # setting
auto-mapping-behavior: full
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
type-aliases-package: com.my.ssm.pojo #
mapper-locations: classpath:/mappers/*.xml # mapperxml的位置
4.新建Mapper相关文件和CustomerController.java
public interface UserMapper {
User findUserByUsername(String username);
}
<!-- namespace = 接口的全限定符 -->
<mapper namespace="com.my.ssm.mapper.UserMapper">
<select id="findUserByUsername" resultType="com.my.ssm.pojo.User">
select * from user
where username = #{username}
</select>
</mapper>
@RestController
@RequestMapping("customer")
public class CustomerController {
@GetMapping("firstMethod")
public String firstMethod() {
return "这是自定义Controller的第一个方法";
}
}
5.新建UserDetailServiceImpl.java
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
/**
* SpringSecurity会调用UserDetailsService的loadUserByUsername方法验证用户名是否合法
* @param username
* @return
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
// 1.通过用户名查询User信息
User user = userMapper.findUserByUsername(username);
if (Objects.isNull(user)) {
throw new RuntimeException("用户名不正确");
}
/**
* 此时的User中需要包含用户名信息,用户密码信息,用户权限信息
* 用户名信息: username
* 用户密码信息: 真实密码信息加密处理后的加密信息
* 用户权限信息: 是根据用户名查出的权限字符串信息,这里暂时只处理认证,不处理授权,所以无须查询用户权限信息.
*/
// 2.将User信息封装到UserDetails对象中
UserDetails userDetails = new UserDetailsImpl(user);
return userDetails;
}
}
6.新建SecurityConfig.java
@Configuration
public class SecurityConig extends WebSecurityConfigurerAdapter {
/**
* 用户密码加密处理
* @return
*/
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
7.相关测试
7.1测试BCryptPasswordEncoder
@SpringBootTest
class SpringSecurityDataSourceApplicationTests {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Test
void contextLoads() {
String encode = bCryptPasswordEncoder.encode("123456");
System.out.println(encode);
}
}
这就是123456在BCryptPasswordEncoder密码加密器的作用下,加密之后的字符串形式.我们可以将其复制到数据库中.
7.2测试SpringSecurity是否能够使用数据库的User信息进行校验.
浏览器输入localhost:8080/customer/firstMethod,输入之后会跳转到localhost:8080/login,输入Username为lisi,Password为123456,点击Sign in,
我们发现我们之前调用的customer/firstMethod这个URI又可以被访问了
当我们将URI修改为logout退出登录时,点击Log Out
当我们再次访问customer/firstMethod这个URI时,
发现此时又被拒绝访问了.