前提:已经集成shiro的环境下,shiro自带的权限不足以满足需求,所以想到的这个办法。
目的:判断当前操作用户是否有权限处理这个操作,大概意思就是加入部门概念,判断该用户是否越部门去处理其他部门的数据了
第一步我们先自定义一个aop接口,放在cn.zyx.test.base.shiro.annotion包下。
/**
* 权限注解 用于检查权限 规定访问权限
* 主要用于只能操作自身数据范围内数据
* 总管理员可以通过该权限
* @example @BasicPermission
*/
@Retention(RetentionPolicy.RUNTIME) //始终不会丢弃,运行期也保留该注解
@Target({ElementType.METHOD}) //标注方法注解
public @interface BasicPermission {
/**
* 需要一个标识,去确认去哪里验证是不是该登陆用户的数据范围
*/
String key() default "";
}
我们写完了之后首先哪去controller层做个简单的测试,看看@注解是否出现
/**
* 冻结课程
*
* @author zyx
* @Date 2019年7月2日15点49分
* 关于权限这里,只能是超级管理员/是该课程所属的门店的管理员,才能冻结或者解冻课程
*/
@RequestMapping("/freeze")
@BasicPermission(key="course")
@ResponseBody
public ResponseData freeze(@RequestParam Integer courseId) {
if (ToolUtil.isEmpty(courseId)) {
throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
}
this.courseService.setCourseState(courseId, BasicSysState.FREEZED.getCode());
return SUCCESS_TIP;
}
然后去实现aop切面类:
/**
* 权限检查的aop
*
* @author zyx
* @date 2019年7月2日15点52分
*/
@Aspect
@Component
@Order(200)
public class BasicPermissionAop {
@Autowired
private PermissionCheckService check;
//这里annotation里放的就是上面注解所在的位置,我们要切入该注解里
@Pointcut(value = "@annotation(cn.zyx.test.base.shiro.annotion.BasicPermission)")
private void cutPermission() {
}
@Around("cutPermission()")
public Object doPermission(ProceedingJoinPoint point) throws Throwable {
MethodSignature ms = (MethodSignature) point.getSignature();
Method method = ms.getMethod();
BasicPermission BasicPermission = method.getAnnotation(BasicPermission.class);
String aopValue = point.getArgs()[0].toString();//获取请求参数id
String aopKey = BasicPermission.key();//获取注解里写的key
//如果当前用户是管理员,则不需要去范围权限进行检查
if(!ShiroKit.isAdmin()) {
//范围权限检查
boolean result = check.checkDataScope(aopKey,aopValue);
if (result) {
return point.proceed();
} else {
throw new NoPermissionException();
}
}
return point.proceed();
}
}
到这里为止,整个流程就实现完成了,后面贴一下我详细权限检查过程,方便以后自己查看。
/**
* 检查用接口
*/
public interface PermissionCheckService {
/**
* 检查当前登陆用户是否操作的是他所在的数据
*/
boolean checkDataScope(String key,String value);
}
/**
* 权限自定义检查
*/
@Service
@Transactional(readOnly = true)
public class PermissionCheckServiceServiceImpl implements PermissionCheckService {
@Override
public boolean checkDataScope(String key,String value) {
//获取当前登陆人的部门所对应的商店/部门
Shop shop = ShiroKit.getDeptShopDataScope();
//根据前端传参的key与value,获取对应的shopId,如果没有,会返回-1
Integer keyId = -1;
/**
* 暂时怎么写,等以后攒多了if判断语句,统一改成策略模式
*/
//BasicPermissionConstant.COURSE="course",写在另外一个静态常量类里
if(BasicPermissionConstant.COURSE.equals(key)) {
Course course = new Course();
course.setId(Integer.valueOf(value));
course = courseMapper.selectOne(new QueryWrapper<Course>(course));
if(ToolUtil.isNotEmpty(course) && ToolUtil.isNotEmpty(course.getShopId())) {
keyId = course.getShopId();
}
}
if(keyId.equals(shop.getId())) {
return true;
}
return false;
}
}