第3章-SaaS系统用户权限设计
学习目标: 理解RBAC模型的基本概念及设计思路 了解SAAS-HRM中权限控制的需求及表结构分析 完成组织机构的基本CRUD操作 完成用户管理的基本CRUD操作 完成角色管理的基本CRUD操作
1 组织机构管理
1.1 需求分析
1.1.1 需求分析 实现企业组织结构管理,实现部门的基本CRUD操作
1.2 微服务实现
下面就是关于部门微服务相关的增删改查操作
部门的Dao接口
/**
* 部门dao接口
*/
public interface DepartmentDao extends JpaRepository<Department,String> ,JpaSpecificationExecutor<Department> {
}
部门的Service接口
@Service
public class DepartmentService extends BaseService {
@Autowired
private DepartmentDao departmentDao;
@Autowired
private IdWorker idWorker;
/**
* 1.保存部门
*/
public void save(Department department) {
//设置主键的值
String id = idWorker.nextId()+"";
department.setId(id);
//调用dao保存部门
departmentDao.save(department);
}
/**
* 2.更新部门
*/
public void update(Department department) {
//1.根据id查询部门
Department dept = departmentDao.findById(department.getId()).get();
//2.设置部门属性
dept.setCode(department.getCode());
dept.setIntroduce(department.getIntroduce());
dept.setName(department.getName());
//3.更新部门
departmentDao.save(dept);
}
/**
* 3.根据id查询部门
*/
public Department findById(String id) {
return departmentDao.findById(id).get();
}
/**
* 4.查询全部部门列表
*/
public List<Department> findAll(String companyId) {
/**
* 用户构造查询条件
* 1.只查询companyId
* 2.很多的地方都需要根据companyId查询
* 3.很多的对象中都具有companyId
*
*/
// Specification<Department> spec = new Specification<Department>() {
// /**
// * 用户构造查询条件
// * root :包含了所有的对象数据
// * cq :一般不用
// * cb :构造查询条件
// */
// public Predicate toPredicate(Root<Department> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
// //根据企业id查询
// return cb.equal(root.get("companyId").as(String.class),companyId);
// }
// };
return departmentDao.findAll(getSpec(companyId));
}
/**
* 5.根据id删除部门
*/
public void deleteById(String id) {
departmentDao.deleteById(id);
}
}
部门Controller接口
//1.解决跨域
@CrossOrigin
//2.声明restContoller
@RestController
//3.设置父路径
@RequestMapping(value="/company") // company/deparment
public class DepartmentController extends BaseController{
@Autowired
private DepartmentService departmentService;
@Autowired
private CompanyService companyService;
/**
* 保存
*/
@RequestMapping(value="/department",method = RequestMethod.POST)
public Result save(@RequestBody Department department) {
//1.设置保存的企业id
/**
* 企业id:目前使用固定值1,以后会解决
*/
department.setCompanyId(companyId);
//2.调用service完成保存企业
departmentService.save(department);
//3.构造返回结果
return new Result(ResultCode.SUCCESS);
}
/**
* 查询企业的部门列表
* 指定企业id
*/
@RequestMapping(value="/department",method = RequestMethod.GET)
public Result findAll() {
//1.指定企业id
Company company = companyService.findById(companyId);
//2.完成查询
List<Department> list = departmentService.findAll(companyId);
//3.构造返回结果
DeptListResult deptListResult = new DeptListResult(company,list);
return new Result(ResultCode.SUCCESS,deptListResult);
}
/**
* 根据ID查询department
*/
@RequestMapping(value="/department/{id}",method = RequestMethod.GET)
public Result findById(@PathVariable(value="id") String id) {
Department department = departmentService.findById(id);
return new Result(ResultCode.SUCCESS,department);
}
/**
* 修改Department
*/
@RequestMapping(value="/department/{id}",method = RequestMethod.PUT)
public Result update(@PathVariable(value="id") String id,@RequestBody Department department) {
//1.设置修改的部门id
department.setId(id);
//2.调用service更新
departmentService.update(department);
return new Result(ResultCode.SUCCESS);
}
/**
* 根据id删除
*/
@RequestMapping(value="/department/{id}",method = RequestMethod.DELETE)
public Result delete(@PathVariable(value="id") String id) {
departmentService.deleteById(id);
return new Result(ResultCode.SUCCESS);
}
}
关于部门下的前端部分的路由设置的界面规划内容
前端页面的和后端的服务端进行连挑
添加界面的功能模块设计
错误日志
添加测试部门
2 RBAC模型
2.1 什么是RBAC RBAC
(全称:Role-Based Access Control)基于角色的权限访问控制,作为传统访问控制(自主访问,强制访 问)的有前景的代替受到广泛的关注。在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些 角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责 任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。角色可依新的需求和系统的合 并而赋予新的权限,而权限也可根据需要而从某角色中回收。角色与角色的关系可以建立起来以囊括更广泛的客观 情况。 访问控制是针对越权使用资源的防御措施,目的是为了限制访问主体(如用户等) 对访问客体(如数据库资源等) 的访问权限。企业环境中的访问控制策略大部分都采用基于角色的访问控制(RBAC)模型,是目前公认的解决大 型企业的统一资源访问控制的有效方法
在RBAC模型中,角色是系统根据管理中相对稳定的职权和责任来划分,每种角色可以完成一定的职能。用户通过 饰演不同的角色获得角色所拥有的权限,一旦某个用户成为某角色的成员,则此用户可以完成该角色所具有的职 能。通过将权限指定给角色而不是用户,在权限分派上提供了极大的灵活性和极细的权限指定粒度。
表结构设计
下面就是关于用户的增删改查的操作主要是DAO,Service,Controller
下面就是创建新得的用户模块
关于用户的DAO接口
public interface UserDao extends JpaRepository<User,String>,JpaSpecificationExecutor<User> {
}
Service接口
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Autowired
private IdWorker idWorker;
/**
* 1.保存用户
*/
public void save(User user) {
//设置主键的值
String id = idWorker.nextId()+"";
user.setPassword("123456");//设置初始密码
user.setEnableState(1);
user.setId(id);
//调用dao保存部门
userDao.save(user);
}
/**
* 2.更新用户
*/
public void update(User user) {
//1.根据id查询部门
User target = userDao.findById(user.getId()).get();
//2.设置部门属性
target.setUsername(user.getUsername());
target.setPassword(user.getPassword());
target.setDepartmentId(user.getDepartmentId());
target.setDepartmentName(user.getDepartmentName());
//3.更新部门
userDao.save(target);
}
/**
* 3.根据id查询用户
*/
public User findById(String id) {
return userDao.findById(id).get();
}
/**
* 4.查询全部用户列表
* 参数:map集合的形式
* hasDept
* departmentId
* companyId
*
*/
public Page findAll(Map<String,Object> map,int page, int size) {
//1.需要查询条件
Specification<User> spec = new Specification<User>() {
/**
* 动态拼接查询条件
* @return
*/
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> list = new ArrayList<>();
//根据请求的companyId是否为空构造查询条件
if(!StringUtils.isEmpty(map.get("companyId"))) {
list.add(criteriaBuilder.equal(root.get("companyId").as(String.class),(String)map.get("companyId")));
}
//根据请求的部门id构造查询条件
if(!StringUtils.isEmpty(map.get("departmentId"))) {
list.add(criteriaBuilder.equal(root.get("departmentId").as(String.class),(String)map.get("departmentId")));
}
if(!StringUtils.isEmpty(map.get("hasDept"))) {
//根据请求的hasDept判断 是否分配部门 0未分配(departmentId = null),1 已分配 (departmentId != null)
if("0".equals((String) map.get("hasDept"))) {
list.add(criteriaBuilder.isNull(root.get("departmentId")));
}else {
list.add(criteriaBuilder.isNotNull(root.get("departmentId")));
}
}
return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
}
};
//2.分页
Page<User> pageUser = userDao.findAll(spec, new PageRequest(page-1, size));
return pageUser;
}
/**
* 5.根据id删除用户
*/
public void deleteById(String id) {
userDao.deleteById(id);
}
}
Controller接口
@RequestMapping(value="/sys")
public class UserController extends BaseController {
@Autowired
private UserService userService;
/**
* 保存
*/
@RequestMapping(value = "/user", method = RequestMethod.POST)
public Result save(@RequestBody User user) {
//1.设置保存的企业id
user.setCompanyId(companyId);
user.setCompanyName(companyName);
//2.调用service完成保存企业
userService.save(user);
//3.构造返回结果
return new Result(ResultCode.SUCCESS);
}
/**
* 查询企业的部门列表
* 指定企业id
*/
@RequestMapping(value = "/user", method = RequestMethod.GET)
public Result findAll(int page, int size, @RequestParam Map map) {
//1.获取当前的企业id
map.put("companyId",companyId);
//2.完成查询
Page<User> pageUser = userService.findAll(map,page,size);
//3.构造返回结果
PageResult pageResult = new PageResult(pageUser.getTotalElements(),pageUser.getContent());
return new Result(ResultCode.SUCCESS, pageResult);
}
/**
* 根据ID查询user
*/
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public Result findById(@PathVariable(value = "id") String id) {
User user = userService.findById(id);
return new Result(ResultCode.SUCCESS, user);
}
/**
* 修改User
*/
@RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
public Result update(@PathVariable(value = "id") String id, @RequestBody User user) {
//1.设置修改的部门id
user.setId(id);
//2.调用service更新
userService.update(user);
return new Result(ResultCode.SUCCESS);
}
/**
* 根据id删除
*/
@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
public Result delete(@PathVariable(value = "id") String id) {
userService.deleteById(id);
return new Result(ResultCode.SUCCESS);
}
}
前端页面设置