美文网首页程序员
Java注解实现权限管理

Java注解实现权限管理

作者: Rechel_uniq | 来源:发表于2020-07-12 20:08 被阅读0次

    一个简单的权限控制场景,已知登录用户id,判断这个用户是否存在数据库中,如果不存在则不允许进行任何操作。

    关于java注解介绍请参见 Java自定义注解实现权限管理

    基础实现

    在每个controller方法中添加用户校验代码,这种可以控制到方法级,但是每个方法都要维护这段重复逻辑。

    @RequestMapping(value = "/task/progress", method = RequestMethod.GET)
        public RestRsp getLabelTaskProgress(
                @RequestParam(name = "taskId", defaultValue = "-1") long taskId,
                @Visitor long userId
        ) {
            // 校验用户
            if (!labelService.checkUserValid(userId)) {
                return RestRsp.success(new ListRsp());
            }
    
            // 获取标注进度
            ... 省略
            return RestRsp.success(listRsp);
        }
    

    拦截器实现

    spring的拦截器实现,好处是增加在进入controller方法前提前拦截非法用户,但是设计到不同controller类或方法不同权限时,只能通过api路径区分,不方便。

    @Slf4j
    public class AuthInterceptor extends HandlerInterceptorAdapter {
    
        private final static String LABEL_PATH_PATTERN = "^/*webapi/+label/*.*$";
        private static final String ERROR_MSG = "您没有权限,请联系管理";
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                Object handler) {
            if (debugHost() && hasDebugParam(request)) {
                return true;
            }
    
            String uri = request.getRequestURI();
            log.info("uri:{}", uri);
            String username = SsoUserInfo.getUserName();
    
            if (Pattern.matches(LABEL_PATH_PATTERN, uri)) {
                Set<String> managerSet = LABEL_MANAGER_SET.get();
                if (!managerSet.contains(username)) {
                    throw new ServiceException(ErrorCode.PERMISSION_DENIED);
                }
    
            } else {
                Set<String> userSet = USER_SET.get();
                if (!userSet.contains(username)) {
                    throw ServiceException.ofMessage(ErrorCode.PERMISSION_DENIED, ERROR_MSG);
                }
            }
            return true;
        }
    }
    
    

    注解实现

    注解+拦截器的实现方式,既可以实现不同粒度的权限控制,也可以集中管理权限。

    • 定义权限枚举变量
    public enum  AuthEnum {
    
        USER_LABEL("label_user", "标注用户", "非标注用户禁止使用"),
        ;
    
        private String code;
        private String desc;
        private String info;
    
        AuthEnum(String code, String desc, String info) {
            this.code = code;
            this.desc = desc;
            this.info = info;
        }
    
        public String getCode() {
            return this.code;
        }
    
        public String getDesc() {
            return this.desc;
        }
    
        public String getInfo() {
            return this.info;
        }
    }
    
    • 定义注解
    @Documented
    @Retention(value = RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD, ElementType.TYPE})
    public @interface AuthAnn {
        AuthEnum[] authType();
    }
    
    • 定义拦截器
    @Slf4j
    @Component
    public class AuthInterceptor extends HandlerInterceptorAdapter {
    
        @Autowired
        private LabelService labelService;
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                Object handler) {
    
            Long userId = SSOHelper.getUserId(request);
    
            AuthAnn authAnn = ((HandlerMethod) handler).getMethodAnnotation(AuthAnn.class);
            if (authAnn == null || ObjectUtils.isEmpty(authAnn.authType())) {
                authAnn = handler.getClass().getAnnotation(AuthAnn.class);
            }
            if (authAnn == null || ObjectUtils.isEmpty(authAnn.authType())) {
                return true;
            }
    
            //log.info("userId:{}", userId);
            AuthEnum[] authEnums = authAnn.authType();
    
            for (AuthEnum authEnum : authEnums) {
                if (AuthEnum.USER_LABEL.equals(authAnn)) {
                    if (!labelService.checkUserExist(userId)) {
                        log.info("Invalid Label User, userId:{}", userId);
                        throw ServiceException.ofMessage(ErrorCode.PERMISSION_DENIED, authEnum.getInfo());
                    }
                }
            }
            return true;
        }
    }
    
    • 注册拦截器
    @Configuration
    @Slf4j
    public class ProphetInterceptorConfiguration implements WebMvcConfigurer {
        @Autowired
        private AuthInterceptor authInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) { 
            String[] paths = passportProperties.urlPaths();
            registry.addInterceptor(AuthInterceptor).addPathPatterns(paths);
        }
    }
    
    • 添加权限
    @Slf4j
    @RestController
    @RequestMapping("/api/label")
    @AuthAnn(authType = AuthEnum.USER_LABEL)
    public class LabelController {
    
    }
    

    相关文章

      网友评论

        本文标题:Java注解实现权限管理

        本文链接:https://www.haomeiwen.com/subject/kpyncktx.html