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 {

}
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值