Java注解实现权限管理

一个简单的权限控制场景,已知登录用户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 = ((HandlerMethod) handler).getBeanType().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(authEnum)) {
     
                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,系统开发,java,spring,注解,注释,@Retention)