学习总结录 学习总结录
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
  • 案例实践

  • 工具使用

  • 项目搭建

  • 服务治理

    • 服务治理-统一白名单
      • 一、需求背景
      • 二、方案设计
      • 三、实现方案
        • 1、自定义注解
        • 2、白名单配置获取
        • 3、白名单加载
        • 4、切面实现
      • 四、案例测试
        • 1、依赖引入
        • 2、配置文件配置白名单用户
        • 3、接口方法使用注解
      • 参考
    • 服务治理-超时熔断
    • 服务治理-调用限流
    • 服务治理-自定义拦截
  • ORM框架

  • MiniSpring

  • 案例归档
  • 服务治理
旭日
2023-04-18
目录

服务治理-统一白名单

# 一、需求背景

现在有业务A和业务B,其中业务A是新业务,业务B是需要修改的业务:

  • 新业务需要多方测试、而且上线后不一定面向所有的用户群体,可能针对部分VIP用户开放接口。
  • 老业务有大量的用户沉淀,可能需要针对老用户进行一定条件限制。

为了更好的控制系统风险,需要在代码接口层提供白名单控制,但是如果白名单控制放在业务代码里面,如果后续设计到变动,就会有很多代码的修改操作,所以我们需要开发一个白名单中间件服务系统。

# 二、方案设计

白名单服务属于业务系统开发过程中可重复使用的通用功能,所以需要将这样的功能单独形成一个组件,让需要进行验证的请求,统一经过白名单中间件。

  • 使用注解、切面技术实现自定义注解
  • 通过SpringBoot对配置文件的处理方式,把白名单配置到配置文件中
  • 通过指定字段的入参和白名单配置文件进行匹配
    • 通过,允许访问接口
    • 不通过,直接截断

# 三、实现方案

# 1、自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoWhiteList {

    String key() default "";

    String returnJson() default "";
}
  • Target(ElementType.METHOD):针对的目标,这个注解适用于方法。
  • Retention(RetentionPolicy.RUNTIME): 信息会被带到JVM运行时,可以通过反射拿到注解信息。

# 2、白名单配置获取

@ConfigurationProperties("demo.whitelist")
public class WhiteListProperties {

    private String users;

    public String getUsers() {
        return users;
    }

    public void setUsers(String users) {
        this.users = users;
    }
}

通过@ConfigurationProperties注解,就可以在配置文件中读取到我们设定的配置信息。

# 3、白名单加载

@Configuration
@ConditionalOnClass(WhiteListProperties.class)
@EnableConfigurationProperties(WhiteListProperties.class)
public class WhiteListAutoConfigure {

    @Bean("whiteListConfig")
    @ConditionalOnMissingBean
    public String whiteListConfig(WhiteListProperties properties) {
        return properties.getUsers();
    }

}
  • 通过@Configuration将这个类指定成一个组件
  • @ConditionalOnClass是当WhiteListProperties位于当前类路径上,才会实例化一个类
  • @Bean是声明为一个Bean,这时候会涉及属性注入,注入的过程会涉及到properties实例化

# 4、切面实现

@Aspect
@Component
public class DoJoinPoint {

    private final Logger logger = LoggerFactory.getLogger(DoJoinPoint.class);

    @Resource
    private String whiteListConfig;

    @Pointcut("@annotation(me.xu.whitelist.annotation.DoWhiteList)")
    public void aopPoint() {
    }

    @Around("aopPoint()")
    public Object doRouter(ProceedingJoinPoint point) throws Throwable {
        // 获取方法
        Method method = getMethod(point);

        // 注解
        DoWhiteList whiteList = method.getAnnotation(DoWhiteList.class);

        // 获取字段值
        String keyValue = point.getArgs()[0].toString();
        logger.info("middleware whitelist handler method:{} value:{}", method.getName(), keyValue);
        if (null == keyValue || "".equals(keyValue)) {
            return point.proceed();
        }
        String[] split = whiteListConfig.split(",");
        // 白名单过滤
        for (String str : split) {
            if (keyValue.equals(str)) {
                return point.proceed();
            }
        }
        // 拦截
        return returnObject(whiteList, method);
    }

    // 获取方法
    private Method getMethod(JoinPoint point) {
        Signature sig = point.getSignature();
        MethodSignature methodSignature = (MethodSignature) sig;
        return methodSignature.getMethod();
    }

    // 返回对象
    private Object returnObject(DoWhiteList whiteList, Method method) throws IllegalAccessException, InstantiationException {
        Class<?> returnType = method.getReturnType();
        String returnJson = whiteList.returnJson();
        if ("".equals(returnJson)) {
            return returnType.newInstance();
        }
        return JSON.parseObject(returnJson, returnType);
    }

}

# 四、案例测试

# 1、依赖引入

创建一个新的SpringBoot项目,然后引入白名单依赖:

    <dependency>
        <groupId>me.xu</groupId>
        <artifactId>spring-whitelist</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

# 2、配置文件配置白名单用户

server:
  port: 8081

demo:
  whitelist:
    users: aaa,111,wxx

# 3、接口方法使用注解

@RestController
public class UserController {

    private Logger logger = LoggerFactory.getLogger(UserController.class);

    /**
     * 通过:http://localhost:8081/api/queryUserInfo?userId=aaa
     * 拦截:http://localhost:8081/api/queryUserInfo?userId=123
     */
    @DoWhiteList(key = "userId", returnJson = "{\"code\":\"1111\",\"info\":\"非白名单可访问用户拦截!\"}")
    @RequestMapping(path = "/api/queryUserInfo", method = RequestMethod.GET)
    public UserInfo queryUserInfo(@RequestParam String userId) {
        logger.info("查询用户信息,userId:{}", userId);
        return new UserInfo("wxx:" + userId, 19, "地址");
    }

}

# 参考

服务治理-统一白名单控制 (opens new window)

上次更新: 2024/06/29, 15:13:44
对象存储搭建静态博客
服务治理-超时熔断

← 对象存储搭建静态博客 服务治理-超时熔断→

最近更新
01
基础概念
10-31
02
Pytorch
10-30
03
Numpy
10-30
更多文章>
Theme by Vdoing | Copyright © 2021-2024 旭日 | 蜀ICP备2021000788号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式