Spring Security 作为安全框架包含类两大核心的模块:认证与鉴权。在前两篇文章中展现了 Spring Security 中的认证模块一些内容,紧接着这篇文章会将目光放到 Spring Security 的鉴权模块中。介绍一下在 Spring Security 中如何使用鉴权功能。
那接下来就看一看在 Spring Security 中如何实现基于角色的访问控制吧!
本文配套的示例源码: https://github.com/lxiaocode/spring-security-examples
在我的博客阅读本文会有更好的阅读体验哦!博客: www.lxiaocode.com
本系列的其他文章,推荐按顺序阅读:
你将会学到什么
- Spring Security 是如何获取用户角色信息的。
- Spring Security 的角色是以什么形式表示的。
- 在登录时如何获取用户角色并返回给 Spring Security 进行认证授权。
- 如何配置角色的访问权限。
1. 准备工作
1.1 创建 Spring Security 项目
在实现功能之前当然要先创建好项目啦。如果学习过我前两篇文章的话,创建一个 Spring Security 项目可以说是非常轻松了。因为这篇文章的示例是基于 {% post_link Spring-Security-接入数据库中的数据 %} 进行扩展的,所以推荐先学习一下这篇文章。
首先,这篇文章会在 {% post_link Spring-Security-接入数据库中的数据 %} 的基础上实现 Spring Security 基于角色的访问控制。所以需要先搭建一个已接入数据库用户的 Spring Security 项目。因为这涉及到了上一篇文章的内容,所以接下来会简单快速的创建项目,不再进行说明了。
1.1.1 导入依赖项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 本文使用 MyBatis-Plus 连接数据库 -->
<!-- 使用什么的方法都可以,只要从数据库查询到数据就行 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.0</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
1.1.2 创建用户类以及相关类
@TableName("user")
public class User implements UserDetails {
private String id;
private String username;
private String password;
/**
* 表示该属性不为数据库表字段,但又是必须使用的。
*/
@TableField(exist = false)
private Set<? extends GrantedAuthority> authorities;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.authorities;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
public void setAuthorities(Set<? extends GrantedAuthority> authorities) {
this.authorities = authorities;
}
//账号是否过期
@Override
public boolean isAccountNonExpired() {
return true;
}
//账号是否锁定
@Override
public boolean isAccountNonLocked() {
return true;
}
//账号凭证是否未过期
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
// 省略 getter setter ...
}
public interface UserMapper extends BaseMapper<User> {
}
@Service
public class UserService implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username", username);
User user = userMapper.selectOne(wrapper);
if (user == null){
throw new UsernameNotFoundException("用户不存在");
}
return user;
}
}
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
}
好了,现在就完成 Spring Security 项目的创建并且接入了数据库中的数据了(当然,其中省略了数据库、扫描 Mapper 的相关配置 )。
1.2 数据库表
在基于角色的访问控制中,我们需要有与用户相绑定的角色信息。所以下面会给出本文示例中所用到的数据库表结构,以便参考。
-- spring_security.`user` definition
CREATE TABLE `user` (
`id` varchar(32) CHARACTER SET utf8mb4 NOT NULL COMMENT '主键,ID',
`username` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '用户名',
`password` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '用户密码',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
INSERT INTO spring_security.`user` (id,username,password) VALUES
('a4ff5fa9eb9593d335a7e5455de98031','admin','$2a$10$4KL3EiD.TGgcer2l6hSQ1uzuz6kyj6FeqpRR5hhagyNE8f75/FL1S')
,('a4ff5fa9eb9593d335a7e5455de98032','superadmin','$2a$10$lsrIhZQv9HKRFePBBKXFruIM5Yc/YHHNIQL9yy83YBMX9zUf4amCm')
,('a4ff5fa9eb9593d335a7e5455de9803d','user','$2a$10$XZXK3uQw6m0mYAvH5TyyuOxbbEaXICIu1DFv/WJD4v718duRdKGqm')
;
-- spring_security.`role` definition
CREATE TABLE `role` (
`id` int(11) NOT NULL COMMENT '主键,ID',
`role` varchar(100) CHARACTER SET utf8mb4 NOT NULL COMMENT '角色的字符串表示',
`role_name` varchar(100) CHARACTER SET utf8mb4 DEFAULT NULL