跳至主要內容

【Da-API】⑨平台功能扩展

holic-x...大约 7 分钟项目Da-API平台

【Da-API】⑨平台功能扩展

1.问题分析

(1)URL存储和校验规则依托?

​ 此处要梳理一个流程,请求配置必须通过网关转发到对应接口服务地址,因此此处要对url进行处理(后台调用访问的是网关IP+请求路径,网关验证的是真实URL完整路径)

​ 因此要么url中保存完整的URL请求信息,要么在后台调用和网关验证处理的时候对URL进行解析,分别进行验证(项目中一开始没有对URL做处理,导致后台调用和网关验证用的都是URL,这样就会存在冲突)

【1】假设URL存储的是网关IP+请求路径:后端直接访问URL就会经过网关,网关转发请求源变为接口IP+请求路径,如果后端校验直接拿request的路径做验证则肯定会拿不到数据(因为网关和接口的IP不同),所以要注意处理

【2】假设URL存储的是接口IP+请求路径:后端直接访问URL不经过网关,直接访问的是接口信息,导致网关拦截失效。这样虽然校验是通过的但是网关没有起到作用

​ 解决方案:接口URL不存储任何IP信息,只是存储接口路径(不同平台接入可以指定规则,例如加上一个唯一标识项目名,进行接口平台的区分,例如此处前缀都为/api表示这些配置接口都是从api-platform-interface这个项目提供的,以此类推)

image-20240317212657200

​ 调用网关服务IP拼接,可以在api-platform-backend的application.yml文件中设置网关服务IP,通过Springboot提供的@Value注解动态获取参数配置(类似的api-platform-gateway要调用实际接口IP+请求路径也可通过这种方式,但考虑到这个实际接口IP应该是对应到不同项目中的,不应该写死在代码中,因此要将实际接口IP存储到数据库字段中提供查询即可)

优化思考

【1】接入不同平台接口,api-platform-interface提供不同的接口

【2】api-platform-sdk依据不同平台接口的接入做优化,例如一开始简单的get、post请求和文本相应,后续是否可以扩展到图片、视频等

【3】api-platform-backend项目完善优化也要注意

(2)如何接入新的接口?接入流程

思考一个问题:用户开发了一个新接口,要怎么接入这个平台:

【1】开发者在系统中注册用户,申请ak、sk配置信息

【2】以api-platform-interface为例,开发接口,对外提供配置:http://localhost:8080/api/xxxx(接口配置url遵循/api/项目名/xxx接口),由gateway转发到对应的IP地址和接口路径

【3】如果接口接入处理的内容比较负责,则相应的api-platform-sdk也要相应进行版本迭代

【4】api-platform-gateway:网关路由配置,相应的要注意修改网关路由配置(例如此处如果新建一个Controller又指定了/api/xxx/getXXX这样的子路径,相应地要对其进行配置),实际上正常来说如果网关构建完成,如果每接入一个接口都要修改一次网关配置这样会非常麻烦,可以确认是否存在其他网关配置的方式实现这种动态化

image-20240317221513601

image-20240317222211303

PS:此处有个问题存疑,几个后端项目之间的连接访问如果通过ip访问会报403错误,但是如果设置localhost访问则正常

API免费调用平台open in new window

(3)接口如何控制调用次数

​ 【1】bug fix:在gateway中调用方法统计信息,逻辑是根据interfaceInfoId、userId找到关联的记录,如果记录不存在则无任何更新操作(因此接口调用次数要提供一个入口供其生成,例如提供给用户一个申请调用接口的入口)

​ (1)管理员创建接口的时候默认为其分配100次调用该接口的次数

​ (2)用户自主申请某个接口调用此处

​ 从而解决了接口调用绑定关系的记录新增,后面每次接口调用则根据上述操作进行更新即可(否则没有记录就会导致新增的接口接入无法进行统计)

(4)响应数据规范化

​ 设定统一的异常处理格式和数据响应结果,便于跟踪系统联调问题,打印详细系统日志

​ todo:申请接口调用次数扩展

​ 思考项目如何接入平台

​ 提供一些可用的接口信息测试

​ 美化页面设计

​ 传入参数为空待处理

(5)染色数据拦截器

​ api-platform-gateway:配置请求头染色

​ api-platform-interface:定义染色数据拦截器对数据进行拦截处理

2.项目完善

(1)api-platform-interface引入接口文档,便于新增接口测试

【1】pom.xml中加载依赖

 <!-- 通过knife4进行模拟接口测试 -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
            <version>4.4.0</version>
        </dependency>

【2】application.yml配置接口文档,配置生成接口文档源

# 接口文档配置
knife4j:
  enable: true
  openapi:
    title: "Di-API-Interface 接口文档"
    version: 1.0
    group:
      default:
        api-rule: package
        api-rule-resources:
          - com.noob.apiinterface.controller

【3】启动项目

​ 访问:http://localhost:8080/api/doc.html#/home

image-20240318124402383

(2)请求头染色

​ 设定染色数据,backend请求转发到gateway的请求头设定染色数据DYE_DATA_HEADER、DYE_DATA_VALUE,随后interface接收转发的请求通过拦截器进行染色数据校验,如果不满足指定的校验规则(即说明当前这个请求数据不是从平台接入的进而拒绝访问)

api-platform-gateway:设定染色数据,有两种实现方式

【1】在application.yml中配置默认过滤器

# 网关配置
spring:
  cloud:
    gateway:
      # config default-filters
      default-filters:
        - AddRequestHeader=myGatewayHeader,swag

【2】在自定义全局过滤器中装载配置

   		------------------- 业务代码实现 -------------------------				
							// 流量染色,只有染色数据才能被调用
                ServerHttpRequest modifiedRequest = exchange.getRequest().mutate()
                        .header(CommonConstant.DYE_DATA_HEADER, CommonConstant.DYE_DATA_VALUE)
                        .build();

                ServerWebExchange serverWebExchange = exchange.mutate()
                        .request(modifiedRequest)
                        .response(decoratedResponse)
                        .build();

                // 设置 response 对象为装饰过的
                return chain.filter(serverWebExchange);

api-platform-interface:配置拦截器校验染色数据

​ 校验数据是否由指定平台转发(进而实现访问控制),双方约定好相应的染色数据,进而进行接口访问控制

【1】自定义Web拦截器

/**
 * 染色数据拦截器
 */
@Slf4j
public class DyeDataInterceptor implements HandlerInterceptor {

    // 染色数据(可定义在CommonConstant中,只有接入平台接口才能够使用这个染色数据,此处模拟校验)
    private static final String DYE_DATA_HEADER = "X-Dye-Data";

    private static final String DYE_DATA_VALUE = "noob";

    /**
     * 调用接口时,如果发现是未经过网关染色的请求,不予响应
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 获取请求头中的染色数据
        String dyeData = request.getHeader(DYE_DATA_HEADER);
        log.info("请求头染色数据:{}",dyeData);

        if (dyeData == null || !dyeData.equals(DYE_DATA_VALUE)) {
            // 如果染色数据不存在或者不匹配,则返回错误响应
            log.info("没有获取到当前请求头的染色数据或者请求头染色数据不匹配");
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            return false;
        }

        // 继续向下执行
        return true;
    }
}

【2】配置装载

@Configuration
public class MyWebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new DyeDataInterceptor())
                .addPathPatterns("/**").excludePathPatterns(
                "/doc.html",
                "/webjars/**",
                "/swagger-resources",
                "/v3/api-docs",
                "/v2/api-docs"
        );
    }
}

调试

​ 配置上述内容,数据染色,如果直接测试api-platform-interface接口则需要相应配置请求头,可在api文档中配置全局参数设置请求头以进行校验

image-20240318132030127

BUG-FIX

【1】编码格式

# 方式1:借助hutools处理
String body = URLUtil.decode(request.getHeader("body"), CharsetUtil.CHARSET_UTF_8);
 URLUtil.encode(body, CharsetUtil.CHARSET_UTF_8);


# 方式2:借助URLEncoderURLDecoder处理
URLEncoder.encode(body,"utf-8")
String body = URLDecoder.decode(headers.getFirst(APIHeaderConstant.BODY), "utf-8");


如果两种方式不统一的话可能造成sign编码解码出现不一致的情况,导致sign验证失效(因为sign是需要body混淆的)

【2】日期显示(后端响应配置)

// 1.引入依赖
<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-annotations</artifactId>
   <version>2.13.3</version>
   <optional>true</optional>
</dependency>


// 2.在对应实体字段中加入json日期格式化
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
  
// 3.api-platform-common重新打包,在其他项目中引用更新

【3】前端美化

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.1.3