小程序的权限拦截

发布时间:2024-01-02 18:30

需求:
懒得做登录了, 只用小程序的openid 来做权限管理,不引用spring的security;
步骤:

  1. 实现方法注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD})
public @interface HasRole {
    String value();
}

简单实现一个注解,用法

    @HasRole("#deviceOperate.step")
    @PostMapping
    public R insert(@RequestBody DeviceOperate deviceOperate) {
        return success(this.deviceOperateService.save(deviceOperate));
    }
  1. 实现HandlerInterceptor拦截器
    主要用于存放小程序的openId,这边存放完整的用户
@Component
public class HasRoleInterceptor implements HandlerInterceptor {

    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String openId = request.getHeader("open_id");
        if (!StringUtils.hasText(openId)) {
            throw new SecurityException("未找到openId");
        }
        User user = userService.getByOpenId(openId);
        if (user == null) {
            throw new SecurityException("未找到用户");
        }
        UserContext.set(user);
        return true;
    }

}

获取的用户放到上下文中,实现UserContext

public class UserContext implements AutoCloseable {

    static final ThreadLocal ctx = new ThreadLocal<>();

    public static void set(User user) {
        ctx.set(user);
    }

    public static User currentUser() {
        return ctx.get();
    }

    @Override
    public void close() {
        ctx.remove();
    }
}
  1. 实现Aspect方法拦截器
    主要由于HandlerInterceptor实现参数获取,太过复杂, 使用aspect获取更加清晰;
    拦截HasRole注解的,解析里面spel,获取需要的权限。
@Aspect
@Component
public class HasRoleAspect {

    @Autowired
    private UserService userService;

    // Service层切点
    @Pointcut("@annotation(com.hiklife.server.auth.HasRole)")
    public void servicePointcut() {
    }

    // 切点方法执行前运行
    @Before(value = "servicePointcut()")
    public void doBefore(JoinPoint joinPoint) throws NoSuchMethodException {
        // 获取当前访问的class类及类名
        Class clazz = joinPoint.getTarget().getClass();

        // 获取访问的方法名
        String methodName = joinPoint.getSignature().getName();
        // 获取方法所有参数及其类型
        String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        Object[] args = joinPoint.getArgs();
        // 获取访问的方法对象
        Method method = clazz.getDeclaredMethod(methodName,
                                                ((MethodSignature) joinPoint.getSignature()).getParameterTypes());

        // 判断当前访问的方法是否存在指定注解
        if (method.isAnnotationPresent(HasRole.class)) {
            HasRole annotation = method.getAnnotation(HasRole.class);

            // 获取注解标识值与注解描述
            ExpressionParser parser = new SpelExpressionParser();
            Expression expression = parser.parseExpression(annotation.value());
            EvaluationContext context = new StandardEvaluationContext();
            for (int i = 0; i < argNames.length; i++) {
                context.setVariable(argNames[i], args[i]);
            }
            String role = String.valueOf(expression.getValue(context));
            User user = UserContext.currentUser();
            if (user == null || !user.getUserRole().contains(role)) {
                throw new SecurityException("没有权限执行方法");
            }
        }

    }
}

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号