1,什么是数据权限?
举个例子,一个学校的校长能看到学生管理系统的全部学生的信息,进行管理维护 。而一个老师只能维护管理系统中自己班的学生,别的人根本看不到。
简而言之,就是同一张表,不同角色的人看到的是不一样的结果。
2. 场景
对同一个对象,不同的角色可以访问到的对象字段不一样。比如对于员工对象,领导可以看到员工的手机号,而普通人看不到员工的手机号。
针对这个场景,我们可以抽取出两种角色,一种是老板, 一种是员工。
老板可以看到所有人的手机号 , 而员工只能看到自己的手机号。
3. 伪代码实现
1. 基本思路
建立用户表 user
user_id user_name phone delete_mask
1 张三 1321321312 0
2 李四 2133192321 0
假设张三是老板
现在要实现的效果是 , 张三和李四访问同一个接口 , 张三能看到所有人 , 而李四只能看到自己。
首先 查看所有人的信息的sql
select * from user where user_id where delete_mask = 0;
自己只能看自己信息的sql
select * from user where user_id where delete_mask = 0 and user_id = X;
我们把 and user_id = X; 替换为 #{dynamicSql}
最后sql变为了
select * from user where user_id where delete_mask = 0 #{dynamicSql}
如果是老板访问 , 他就不需要拼接 and user_id = X;
如果是员工访问 , 他拼接的sql 都是 AND user_id = ; 其中 X是自己的user_id
2. 后端接口
//我们要求需要这种数据权限的接口都继承一个类
class BaseEntity{
private String dynamicSql;
}
class User extends BaseEntity{
private String userId;
private String userName;
private String phone;
}
@GetMapping("/infoList")
public List<User> getList(User user){
return userMapper.select();
}
3. AOP技术
@DataScope
@GetMapping("/infoList")
public List<User> getList (User user) {
return userMapper.select();
}
//这样上述接口就会被拦截了
4. 切面逻辑
@Before(DataScope.class)
public void doBefore(JoinPoint point , DataScope dataScope)
{
//首先获得 user对象 把它强转为 BaseEntity
Object params = joinPoint.getArgs()[0];
BaseEntity baseEntity = null;
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
}
//获得用户的id(一般都是从threadLocal里面获取)
String userId = getUserId();
//然后去处理 dynamicSql
String dynamicSql = "";
if ("1".equals(userId)) {
//说明是老板 那么他的sql不需要任何拼接
baseEntity.dynamicSql = null;
}
else{
//说明不是老板 那么他的sql需要拼接
dynamicSql = "AND user_id = " + userId;
baseEntity.dynamicSql = dynamicSql;
}
}
5. 动态SQL
<select id="selectPictureList" parameterType="Picture" resultMap="PictureResult">
select * from user where delete_mask = 0
<where>
#{dynamicSql}
</where>
</select>
4. 总结
这里只是做了一个简单的Demo , 但是基本讲清楚了数据权限的原理 , 无非就是通过AOP技术 , 然后去动态地对sql进行拼接。