一,表的结构分析
我的个人思路是用户应该关联着角色,每个角色关联着对应的权限(路径),这个思路分析的话,就要建立五张表。
二,业务代码分析
做权限模块的设计首先要考虑两部分,对于分布式微服务架构,我们可以通过留出来一个专门的接口来给网关调用,进行鉴权,其次我们可以通过一个图形化的界面来帮助我们管理用户,角色,权限,以及它们之间的关联关系。
这样我们的思路就很明确了,接口分为两部分,一部分提供给外部调用,另一部分提供给权限模块自己的图像化界面。
接着再分析对外提供的接口需要做什么?
根据传递过来的用户id来获取对应的权限(可以访问的路径)。
内部接口需要做什么?
用户与角色的关联关系管理,角色的管理,权限的管理,一级角色与权限关联关系的管理。
三,具体代码实现
1.数据库的建表
CREATE DATABASE /*!32312 IF NOT EXISTS*/`security`
USE `security`;
DROP TABLE IF EXISTS `t_path`;
CREATE TABLE `t_path` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`thePath` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
insert into `t_path`(`id`,`thePath`) values (1,'level4'),(2,'level2'),(3,'level1'),(4,'level3');
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`roleName` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
insert into `t_role`(`id`,`roleName`) values (1,'SUPERADMIN'),(2,'ADMIN'),(3,'VIP'),(4,'USER');
DROP TABLE IF EXISTS `t_role_path`;
CREATE TABLE `t_role_path` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`rid` int(11) DEFAULT NULL,
`pid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;
insert into `t_role_path`(`id`,`rid`,`pid`) values (1,1,1),(2,1,2),(3,1,3),(4,1,4),(5,2,1),(6,2,2),(7,2,4),(8,3,1),(9,3,4),(10,4,1);
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) DEFAULT NULL,
`rid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
2.java代码
实体类的设计
接口的设计
圈起来的代表对外提供的接口,其余的都是内部接口
具体接口
/**
* @author yhd
* @createtime 2020/9/6 14:32
*/
@RestController
@RequestMapping("/level4/external")
public class ExternalController {
@Autowired
private UserService userService;
//根据用户id查询对应的路径
@GetMapping("/{uid}")
public List<Path> find(@PathVariable("uid") long uid) {
return userService.findPaths(uid);
}
}
== 内部接口示例==
/**
* @author yhd
* @createtime 2020/9/6 13:40
*/
@RestController
@RequestMapping("/security/level1/role")
public class RoleController {
@Autowired
private RoleService roleService;
@PostMapping("/add")
public String add(Role role) {
roleService.insertRole(role);
return "success";
}
@DeleteMapping("/delete/{id}")
public String delete(@PathVariable("id") Long id) {
roleService.deleteRole(id);
return "success";
}
@PutMapping("/update")
public String update(Role role) {
roleService.updateRole(role);
return "success";
}
@GetMapping("/findAll")
public List<Role> findAll() {
return roleService.findAll();
}
}
/**
* @author yhd
* @createtime 2020/9/6 13:41
*/
@RestController
@RequestMapping("/security/level1/path")
public class PathController {
@Autowired
private PathService pathService;
//添加路径
@PostMapping("/add")
public String add(Path path){
pathService.insertPath(path);
return "success";
}
//删除路径
@DeleteMapping("/delete/{id}")
public String delete(@PathVariable("id") Long id){
pathService.deletePath(id);
return "success";
}
//修改路径
@PutMapping("/update")
public String update(Path path){
pathService.updatePath(path);
return "success";
}
@GetMapping("/findAll")
public List<Path> findAll(){
return pathService.findAll();
}
}
/**
* @author yhd
* @createtime 2020/9/6 13:43
*/
@RestController
@RequestMapping("/security/level1/rolepath")
public class RolePathController {
@Autowired
private RolePathService rolePathService;
@PostMapping("/add/{rid}/{pid}")
public String add(@PathVariable("rid") long rid, @PathVariable("pid") long pid) {
rolePathService.insertRolePath(rid, pid);
return "success";
}
@DeleteMapping("/delete/{rid}/{pid}")
public String delete(@PathVariable("rid") long rid, @PathVariable("pid") long pid) {
rolePathService.deleteRolePath(rid, pid);
return "success";
}
@GetMapping("/find/{rid}")
public List<Path> find(@PathVariable("rid") long rid) {
return rolePathService.findPathByRole(rid);
}
}
/**
* @author yhd
* @createtime 2020/9/6 13:42
*/
@RestController
@RequestMapping("/security/level1/userrole")
public class UserRoleController {
@Autowired
private UserRoleService userRoleService;
@PostMapping("/add/{uid}/{rid}")
public String add(@PathVariable("uid") long uid, @PathVariable("rid") long rid) {
userRoleService.insertUserRole(uid, rid);
return "success";
}
@DeleteMapping("/delete/{uid}/{rid}")
public String delete(@PathVariable("uid") long uid, @PathVariable("rid") long rid) {
userRoleService.deleteUserRole(uid, rid);
return "success";
}
@GetMapping("/find/{uid}")
public List<Role> find(@PathVariable("uid") long uid) {
return userRoleService.findRoleByUser(uid);
}
}
四,扩展
其实这种方式只是适合一些权限比较简单的项目使用,如果对于权限的要求比较高,我们可以考虑给用户首先关联对应的组,组关联角色,角色在关联权限,或者可能有一些要求精细到按钮级别的权限控制,我们可以传递用户对应的角色到前端,前端根据我们提供的角色来控制是否显示对应的按钮。