自定义拦截器实现权限校验

背景

前几天接收到一个业务需求,简要描述一下,当某个企业账户冻结之后,企业在登陆后台管理系统,不能进行某些操作,如导入员工信息、发放员工福利、发票信息申请等,但是系统中的查看功能如账单查询、员工查询都可以正常使用。
很显然,从全局去处理账户的状态判断是不可取的,因为在账户冻结之后,并不是所有的动作都是被禁止的,这里就可以使用过滤器对指定的方法进行筛选校验

既定方案

使用自定义的注解,标注需要进行账户状态校验的请求方法,使用拦截器拦截这些接口,在拦截器中执行账户状态的判断,如果账户状态正产则放行,如果状态异常则抛出自定义的异常,并且使用自定义的异常处理类进行捕获处理。基本思路就是这样,下面我们来进行方案的实现。

方案实现

  • 第一步:自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FrozenAcc {
    boolean permission() default false;
}

方法级别以及运行时状态即可。

  • 第二步:自定义拦截器
@Slf4j
public class FrozenFilter extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //拦截自定义的注解
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        FrozenAcc annotation = handlerMethod.getMethod().getAnnotation(FrozenAcc.class);
        if (annotation == null) {
            return true;
        }
        //获取如果处于冻结状态,则抛出一个异常信息
        String accStatus = UserUtil.getAccStatus();
        if ("1".equals(accStatus)) {
            return true;
        }
        throw new FrozenException(444, "您好,您的账户因逾期未还款已被冻结,无法进行当前操作,请尽快还款后申请解冻!");
    }
}
  • 第三步:注册拦截器类,使拦截器生效
@Configuration
public class CheckConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new FrozenFilter()).addPathPatterns("/employee/enterpriseEmployee/**");
        registry.addInterceptor(new FrozenFilter()).addPathPatterns("/enterprisepoints/enterprisePointsBatch/**");
        registry.addInterceptor(new FrozenFilter()).addPathPatterns("/invoice/**");


    }
    }

可注册多个拦截器,并指定拦截规则,这里我对员工管理、企业积分管理、以及发票信息管理做了拦截

  • 第四步:控制层中,在需要进行账户信息校验的接口上添加注解
 @FrozenAcc
    @RequiresPermissions("tb:enterpriseEmployee:add")
    @PostMapping(value = "add")
    public R add(EnterpriseEmployee enterpriseEmployee) {
        return enterpriseEmployeeService.saveEmployee(enterpriseEmployee);
    }

如上,在员工管理中,新增员工信息的方法上面添加FrozenAcc注解

  • 第五步:自定义异常以及异常处理

自定义异常类,用于拦截器中校验账户状态时,不符合时抛出

@Data
@EqualsAndHashCode(callSuper = false)
public class FrozenException extends RuntimeException {

    private int code;
    private String message;


    public FrozenException(int code, String message) {
        this.message = message;
        this.code = code;
    }
}

异常处理类,用于捕获处理自定义的异常,封装响应参数给前端

@ExceptionHandler(FrozenException.class)
    public R handleFrozenException(FrozenException e) {
        return R.fail(e.getCode(), e.getMessage());
    }

总结

以上就可以实现对指定接口实现账户状态的校验,能够符合业务的需要,但是还是存在改进之处的。

在请求指定模块时,凡是加上注解的方法都需要去校验账户的状态,目前是采取直查数据库的方式,在日志中能发现多次查询的sql语句,一个是增加系统的IO开销,还有就是重复的查询逻辑,之前有考虑过在用户登录之后,就将企业的账户状态放到全局的会话缓存当中,但是有个弊端就是,如果用户在登陆成功之后,账户状态过期冻结,那么这个 用户还是可以进行操作的,并没有达到实时的状态过滤。

可以引入缓存机制,提高性能,但是必须还得配上缓存的更新策略。可优化的方案如下:

  • 登录时,将企业的账户状态放到redis缓存中,并在企业账户状态变更的逻辑中(具体的操作或者定时任务等),添加账户状态的更新逻辑,将最新的状态更新至redis当中。而在拦截器中,就可以直接使用redis中的值来判断企业的账户状态,使用缓存提升查询效率避免直查数据库。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值