1 Star 0 Fork 0

Yi / 猿接口-Backend

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

API-Back

猿接口平台主要功能:管理员可以接入并发布接口,统计分析各接口调用情况;用户可以注册登录并开通接口调用权限,然后可以浏览接口及在线调试,还能使用客户端 SDK 轻松在代码中调用接口。

架构图

技术选型

  • Java Spring Boot
  • MySQL 数据库
  • MyBatis-Plus 及 MyBatis X 自动生成
  • API 签名认证(Http 调用)
  • Spring Boot Starter(SDK 开发)
  • Dubbo 分布式(RPC、Nacos)
  • Swagger + Knife4j 接口文档生成
  • Spring Cloud Gateway 微服务网关
  • Hutool、Apache Common Utils、Gson 等工具库

Focal Point

客户端 SDK

开发人员在调用其他接口时,开发人员考虑使用HTTP调用,不仅要考虑接口地址、接口请求方式、接口请求参数、接口返回参数,同时HTTP调用方式还有多种调用方式,例如HttpClient、RestTemplate、Feign、第三方库OKHttp、Hutool等;HTTP协议发送消息是以明文的方式,不像HTTPS以对称加密、非对称加密、证书效验等方式保证数据安全。

那么开发人员如果要调用一个接口必须要兼顾以上因素,同时调用不同的接口还要不断重复造轮子,这对开发人员来说是个灾难。

所以我们基于此来开发SDK,使开发人员能轻松在代码中调用接口。

InterfaceInfoServiceImp中通过反射调用SDK中不同的接口

//客户端SDK
YiApiClient yiApiClient = new YiApiClient(accessKey, secretKey);
String result = ReflectUtil.invoke(yiApiClient, methodName, args);

SDK整体结构

public class YiApiClient {

    private static final String GATEWAY_HOST = "http://127.0.0.1:8090";

    private String accessKey;

    private String secretKey;

    public YiApiClient(String accessKey, String secretKey) {
        this.accessKey = accessKey;
        this.secretKey = secretKey;
    }
    
    //XXX表示不同的接口
    public String getXXX(String args){
        HttpResponse httpResponse = HttpRequest.get(GATEWAY_HOST + "/api/botian/doutu")
                .addHeaders(getHeaderMap(args))
                .execute();
        String result = httpResponse.body();
        return result;
    }
    
    //保证安全
    private Map<String, String> getHeaderMap(String body) {
        Map<String, String> hashMap = new HashMap<>();
        hashMap.put("accessKey", accessKey);
        hashMap.put("nonce", RandomUtil.randomNumbers(4));
        hashMap.put("body", body);
        hashMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
        hashMap.put("sign", genSign(body, secretKey));
        return hashMap;
    }
}

用户鉴权

为了保证接口调用的安全,要对每个用户进行鉴权,防止任意用户随意调用接口浪费性能,同时黑客可以通过抓包获取到了请求的HTTP报文,然后黑客自己编写了一个类似的HTTP请求,发送给服务器。也就是说服务器处理了两个请求,先处理了正常的HTTP请求,然后又处理了黑客发送的篡改过的HTTP请求。

签名认证

通过http request header头传递参数

参数1: accessKey 调用的标识(复杂,无序,无规律)

参数2: secretKey 密钥 (复杂,无序,无规律)该参数不传递,进行加密生成签名后传递

public static String genSign(String body, String secretKey) {
    Digester sha256 = new Digester(DigestAlgorithm.SHA256);
    String content = body + "." + secretKey;
    return sha256.digestHex(content);
}

服务端通过accessKey从数据库获取secretKey然后一模一样的参数和算法去生成签名,只要和用户传的一致,就表示密钥一致

重放攻击

重放攻击是一种网络安全攻击方式,攻击者通过记录或复制合法的通信数据,并在稍后的时间重播这些数据,以欺骗系统,获得未经授权的访问或执行操作。

解决方案:在通信中使用时间戳和随机数来确保通信数据的唯一性和时效性。

hashMap.put("nonce", RandomUtil.randomNumbers(4));

hashMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));

服务的验证

String nonce = headers.getFirst("nonce");
String timestamp = headers.getFirst("timestamp");
//这里大致演示下,正常情况应该用一个set集合中验证,并在规定时间内清除
if (Long.parseLong(nonce) > 10000L) {
            return handleNoAuth(response);
}
Long currentTime = System.currentTimeMillis() / 1000;
        final Long FIVE_MINUTES = 60 * 5L;
        if ((currentTime - Long.parseLong(timestamp)) >= FIVE_MINUTES) {
            return handleNoAuth(response);
}

API 网关

一方面,当接口每次调用都需要统计接口被调用统计信息,接口开发者需要自己去添加统计代码。例如,每个开发团队都需要自己写一个类似AOP切面的统计方法,我们开发人员还要告诉数据库统计地址,这显示是不合理的。

另一方面,当开发人员使用SDK调用接口时,请求头会添加用户鉴权需要的值,那么进行鉴权的逻辑在哪里实现?接口开发人员吗?如果是这样那么接口开发人员似乎不会在开发接口功能了。

那么如何解决这些问题呢?我们可以考虑当前大型项目中使用的微服务架构,客户端想要使用每个服务,那么必须通过网关(Gateway)来进行路由、统一业务处理才可以访问微服务。

项目中主要使用的网关功能:

  • 路由:起到转发的作用,比如有接口A和接口B,网关会记录这些信息,根据用户访问的地址和参数,转发请求到对应的接口(服务器/集群)

  • 统一业务处理:把每个项目中都要做的通用逻辑放到上层(网关),统一处理,比如本项目的次数统计

  • 统一鉴权:判断用户是否有权限进行操作,无论访问什么接口,我都统一去判断权限,不用重复写

  • 访问控制:黑白名单,比如限制ddos ip

  • 统一日志:将下游项目的文档进行聚合,在一个页面统一查看,主要记录每次的请求和响应

RPC 分布式

我们在API网关中要进行统一业务处理,比如本项目中接口调用次数统计。网关项目比较存粹,没有操作数据库的包,并且还要调用我们之前写过的代码?复制粘贴维护麻烦。怎么去操作数据库,怎么复用之前的方法?

理想情况:直接请求到其他项目的方法

有以下两种方式:

HTTP请求(HTTP Client、RestTemplate、Feign)

  • 提供方提供一个接口(地址,请求方法,参数,返回值)
  • 调用方使用HTTP Client之类的代码包去发送HTTP请求

RPC

  • 开发人员可以像调用本地方法一样去调用远程方法

这里使用RPC更合适,因为HTTP请求需要网关设置很多额外的参数,因此后端服务之间更适合使用RPC调用远程方法。

步骤:

  1. 配置注册中心Nacos,提供服务注册发现
  2. 设置一个公共项目来定义服务接口,服务接口是Dubbo中沟通消费端和服务端的桥梁。
  3. backend项目作为服务提供者(@DubboService),提供3个方法: a. 实际情况应该是去数据库中查是否已分配给用户 b. 从数据库中查询模拟接口是否存在,以及请求方法是否匹配(还可以校验请求参数) c. 调用成功,接口调用次数+1 invokeCount
  4. gateway项日作为服务调用者(@DubboReference),调用这3个方法

空文件

简介

API调用后端基于SpringBoot、MyBatis-Plus、Dubbo、Nacos、Spring Cloud Gateway等技术实现,管理员可以接入并发布接口,统计分析各接口调用情况;用户可以注册登录并开通接口调用权限,然后可以浏览接口及在线调试,还能使用客户端 SDK 轻松在代码中调用接口。 展开 收起
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/giteeygq/ape-interface-backend.git
git@gitee.com:giteeygq/ape-interface-backend.git
giteeygq
ape-interface-backend
猿接口-Backend
master

搜索帮助