前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >通用数据级别权限的框架设计与实现(4)-单条记录的权限控制

通用数据级别权限的框架设计与实现(4)-单条记录的权限控制

作者头像
星痕
发布2018-09-12 11:49:30
5030
发布2018-09-12 11:49:30
举报

查看上篇文章通用数据级别权限的框架设计与实现(3)-数据列表的权限过滤,我们开始在原来的基础上实现单条权记录的权限控制。

相信前面的列表权限控制,很多系统都可以做到,但如何在上面列表的权限过滤中实现通用性

原理:我们在权限过滤中,通过AOP接截相关记录,拦截的时候,我们先判断当前人员是否有角色权限,没有的话,我们生成查询权限的SQL,进行权限查找.

1.先定义生成权限的相关注解,相关注解用于权限拦截,及获取拦截的相关参数.

Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthCheck {
    /**权限校验规则
     * @return
     */
    Class classModel() ;

    /**
     *  判断是否IN查询
     * @return
     */
    boolean isIn() default true;

}

注解AuthCheck用于定义单条记录权限拦截的规则

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public  @interface AuthParam {
}

AuthParam只是用于标记哪个参数用于权限校验.

2.生成权限校验SQL的类AuthFiledFilter修改

  /**
     * 生成对一条记录的权限校限SQL
     * @param id
     * @param valueList
     * @return
     */

    public String getAuthSqlIn(Object id, List valueList){
        StringBuffer sb = new StringBuffer();
        sb.append("select count(1) from ");
        sb.append (this.getSalveTableName() );
        sb.append(" where    ").append(this.getSalveTableField()).append("=").append(id);
        sb.append(" and ");
        sb.append(this.buildLogicIN(this.getSearchUserField(), valueList));
        return sb.toString();
    }

    /**
     * 生成对一条记录的权限校验SQL,用EQ
     * @param id
     * @param userId
     * @return
     */

    public String getAuthSqlEq(Object id,Object userId){
        StringBuffer sb = new StringBuffer();
        sb.append("select count(1) from ");
        sb.append (this.getSalveTableName() );
        sb.append(" where    ").append(this.getSalveTableField()).append("=").append(id);
        sb.append(" and ");
        sb.append(  this.getSearchUserField()).append("=").append(userId);
        return sb.toString();
    }

3.权限拦截判断的类AuthValidatorUtil的规则增加

 //生成校验的
    public static String  getAuthModelSql(String classModel, Object id,boolean isIn) {
        AuthValidatorModel authValidatorModel = AuthConfig.get(classModel);
        if (authValidatorModel == null) {
            return "";
        }
        boolean isAuth = authValidatorModel.getRoles().stream().anyMatch(role -> UserUtil.containRole(role));
        if (isAuth) {
            return "";
        }
        String checkAuthSql="";
        if (isIn) {
            checkAuthSql = authValidatorModel.getAuthFiledFilter().getAuthSqlIn(id, UserUtil.getOrgIds());
        } else {
            checkAuthSql = authValidatorModel.getAuthFiledFilter().getAuthSqlEq(id, UserUtil.getUserId());
        }
        return checkAuthSql;
    }

4.关键对有权限标识注解的权限拦截

@Aspect
@Order(1)
@Component
public class AuchCheckAspect {
    protected final Log logger = LogFactory.getLog(AuchCheckAspect.class);

    @Autowired
    AuthMapper authMapper;

    /**
     * 权限校验
     *
     * @param joinPoint
     * @throws Throwable
     */
    @Before(value = "@annotation( com.starmark.auth.anno.AuthCheck)")
    public void timeAroundAdvice(JoinPoint joinPoint) throws Throwable {
        //相关参数
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        AuthCheck AuthCheck = method.getAnnotation(AuthCheck.class);
        String classModel = AuthCheck.classModel().getName();
        Assert.notNull(classModel, " 权限校验模型不允许为空");
        Object id = null;
        Object[] args = joinPoint.getArgs();
        //从方法中获取相关主键校验参数
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            AuthParam authParam = parameters[i].getAnnotation(AuthParam.class);
            if (authParam != null) {
                id = args[i];
                break;
            }
        }
        AuthValidatorModel authValidatorModel = AuthConfig.get(classModel);
        String checkAuthSql = AuthValidatorUtil.getAuthModelSql(classModel,id,AuthCheck.isIn());
        if (StringUtils.isNotEmpty(checkAuthSql)) {
            boolean isAuth = authMapper.isAuth(checkAuthSql);
            if (!isAuth) {
                throw new AuthCheckException();
            }
        }
    }


}

这里提示一下,AuthMapper是我们执行一条生成的SQL方法,是注入一条SQL,因为SQL是我们后台代码生成的,无须考虑SQL注入的问题

    <!-- 生成 SQL判断有没有权限-->
    <select id="isAuth"  resultType="boolean" >
         ${authSql}
    </select>

5.相关权限的功能使用

@GetMapping(value = "/{id}")
    @AuthCheck(classModel = SysAuthRole.class)
    public Object get(@PathVariable("id") @AuthParam Long id) {
        return sysAuthRoleService.get(id);
    }

6.测试:

打开有权限的记录,正常结果如下:

有权限记录.png

打开没有权限的记录,抛出一个无权限的异常。

无权限记录.png

至此,单条记录的权限拦截已完成!

个人代码已经完成,如需要请打赏后通知我。谢谢.

如果你觉得该文章对你有帮助,麻烦点赞。

欢迎继续查看下篇文章-通用数据级别权限的框架设计与实现(5)-总结与延伸思考

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.05.19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档