Spring Security RBAC 1.0
描述
表:5张。用户-角色-权限以及两张关系表。
user | 说明 |
---|---|
id | |
username | |
password | |
其他 |
role | 说明 |
---|---|
id | |
name | |
其他 |
permission | 说明 |
---|---|
id | |
name | |
code |
user_role | 说明 |
---|---|
id | |
user_id | |
role_id |
role_permission | 说明 |
---|---|
id | |
role_id | |
permission_id |
/* Navicat MySQL Data TransferSource Server : MySQL Source Server Version : 80020 Source Host : localhost:3306 Source Database : rbacTarget Server Type : MYSQL Target Server Version : 80020 File Encoding : 65001Date: 2020-10-08 12:45:43 */SET FOREIGN_KEY_CHECKS=0;-- ----------------------------
-- Table structure for permission
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (`id` int NOT NULL AUTO_INCREMENT,`permission_name` varchar(255) NOT NULL,`permission_code` varchar(255) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;-- ----------------------------
-- Records of permission
-- ----------------------------
INSERT INTO `permission` VALUES ('1', '用户查看', 'USER_SELECT');
INSERT INTO `permission` VALUES ('2', '用户添加', 'USER_INSERT');
INSERT INTO `permission` VALUES ('3', '用户删除', 'USER_DELETE');
INSERT INTO `permission` VALUES ('4', '用户更新', 'USER_UPDATE');-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (`id` int NOT NULL AUTO_INCREMENT,`role_name` varchar(255) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', '超级管理员');-- ----------------------------
-- Table structure for role_permission
-- ----------------------------
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (`id` int NOT NULL AUTO_INCREMENT,`role_id` int NOT NULL,`permission_id` int NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;-- ----------------------------
-- Records of role_permission
-- ----------------------------
INSERT INTO `role_permission` VALUES ('1', '1', '1');
INSERT INTO `role_permission` VALUES ('2', '1', '2');
INSERT INTO `role_permission` VALUES ('3', '1', '3');-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` int NOT NULL AUTO_INCREMENT COMMENT 'id',`username` varchar(255) NOT NULL,`password` varchar(255) NOT NULL,`locked` tinyint(1) NOT NULL DEFAULT '0',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'hzk', 'hzk', '0');-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (`id` int NOT NULL AUTO_INCREMENT,`user_id` int NOT NULL,`role_id` int NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES ('1', '1', '1');
步骤
参考:Spring Security实现RBAC权限管理
1. 配置
数据源+ORM+redis+spring session
# 数据源配置
spring.datasource.username=你的数据库用户名
spring.datasource.password=你的数据库密码
spring.datasource.url=jdbc:mysql://localhost:3306/security_rbac?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Drive
# ORM
mybatis-plus.mapper-locations=classpath:/mapper/*.xml# Hikari 数据源专用配置
# redis配置
# spring-session配置
# thymeleaf配置
spring.thymeleaf.cache=false
2. entity
@Data
public class User implements UserDetails {
@TableId(type = IdType.ASSIGN_ID)private Long id;private String username;private String password;private Boolean locked;private List<Role> roleList;private List<SimpleGrantedAuthority> permissionList;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {
return permissionList;}@Overridepublic boolean isAccountNonExpired() {
return true;}@Overridepublic boolean isAccountNonLocked() {
return !locked;}@Overridepublic boolean isCredentialsNonExpired() {
return true;}@Overridepublic boolean isEnabled() {
return true;}
}@Data
public class Role {
@TableId(type = IdType.ASSIGN_ID)private Long id;private String roleName;
}@Data
public class Permission {
@TableId(type = IdType.ASSIGN_ID)private Long id;private String permissionName;private String permissionCode;
}
3. Repository
@Repository
public interface UserMapper extends BaseMapper<User> {
User selectByUsername(String username);List<Role> selectRoleListById(Long id);List<Permission> selectPermissionListByRIdList(List<Long> ridList);
}
4. Service
@Service
@Slf4j
public class UserService implements UserDetailsService {
@Autowiredprivate UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userMapper.selectByUsername(s);if (user == null) {
throw new UsernameNotFoundException("用户名不存在!");}user.setRoleList(userMapper.selectRoleListById(user.getId()));List<Permission> permissionList = userMapper.selectPermissionListByRIdList(user.getRoleList().stream().map(Role::getId).collect(Collectors.toList()));List<SimpleGrantedAuthority> simpleGrantedAuthorityList = new ArrayList<>(permissionList.size());permissionList.forEach(permission -> simpleGrantedAuthorityList.add(new SimpleGrantedAuthority(permission.getPermissionCode())));user.setPermissionList(simpleGrantedAuthorityList);log.warn("User: {}", user.toString());return user;}
}
5. 配置
登录页面和密码配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Overrideprotected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().and().formLogin().loginPage("/login").failureForwardUrl("/login-error")// .successForwardUrl("/index").permitAll();}@Beanpublic PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();}
}
6. 使用
说明:@EnableGlobalMethodSecurity开启方法注解权限判定
说明:访问/user/index页面需要USER_UPDATE权限,db定义超级管理员权限为SELECT|INSERT|DELETE,测试结果:
@Controller
public class Test {
@PreAuthorize("hasAuthority(T(com.hzk.app.demo.security.Const.Permission).USER_UPDATE)")@RequestMapping("/user/index")public String userIndex() {
return "user/index";}
}
参考
Spring Security实现RBAC权限管理
Spring Security 之方法级的安全管控