阅读 166

基于 spring cloud gateway filter 统一生成阿里云 OSS 文件签名

问题

我们的文件(用户的身份证件,隐私视频等)都放在 阿里云 OSS,OSS Bucket Name 存储空间 的读写权限 设置为 私有,代表 属于这个 bucket name 的文件 都需要经过 身份认证 才能访问。

目前文件 uri 分布在各个服务中,前端 如果需要操作或显示图片,都要通过 OSS SDK 生成可预览 URL 才有权限访问。

那么这个问题就变成,“通过 OSS SDK 生成可预览 URL” 这个职责 应该 交给谁(前端 or 后端)来承担更合适

问题举例

假设这个问题由后端解决,那么就会有以下用例:

给定 /test 接口

并且 /test 接口返回以下数据

{
    "name": "越前龙马",
    "url": "yqlm.jpeg",
    "testItem": {
        "imageUrl": "test111111.png",
        "name": "test111111"
    },
    "testItems": [
        {
            "imageUrl": "test-image.jpeg",
            "name": "test-image"
        }
    ]
}
复制代码

前端调用 /test 接口

那么 前端将得到以下数据

{
    "name": "越前龙马",
    "url": "https://endpoint/yqlm.jpeg?Expires=1571308870&OSSAccessKeyId=xxx&Signature=BdNd1zAcr3r4GZyupVW134W2UQ0=",
    "testItem": {
        "imageUrl": "https://endpoint/test111111.png?Expires=1571308870&OSSAccessKeyId=xxx&Signature=pQUh8SzS+kQnxOkGwoS6NaRTmJs=",
        "name": "test111111"
    },
    "testItems": [
        {
            "imageUrl": "https://endpoint/test-image.jpeg?Expires=1571308870&OSSAccessKeyId=xxx&Signature=KAcEkGb2P68/mFpLoJcak42kMtw=",
            "name": "test-image"
        }
    ]
}
复制代码

解决方案

方案1:前端承担

方案1-前端承担

优势:后端不需要额外调用 OSS SDK API(特别是分页接口比较繁琐)。

劣势:把问题抛给前端,前端有 IOS、Android、和 WEB,导致每个端都需要关注这个问题。

整体上这个方案可行,不过对各个前端不友好,还不是理想的解决方案。

方案2:各个服务自己承担

方案2-各个服务自己承担

优势:各个前端 不需要关注 如何对文件进行身份认证。

劣势:把问题 抛给各个服务的负责人,每个服务 都需要集成 OSS SDK,还需要了解 如何正确使用;而且很明显这些都是 重复代码。

这个方案跟第一个方案差不多,把问题 从前端 抛给了 各个服务,还不是理想的解决方案。

方案3:新增一个文件服务来承担

方案3-新增一个文件服务来承担

优势:职责更加合理,各个服务通过 Feign 或 RPC 跟 文件服务 交互,具体的细节封装在 文件服务 中。

劣势:各个服务 还是需要关注 何时 该调用 文件服务 生成可预览 URL。

通过 增加 文件服务 来承担 生成文件可预览 URL 的职责,消除各个服务的重复的关注点,非常适合私有文件比较少的场景,明显 方案 3 比之前两个方案 都要合理一些,算是一个备选方案。

方案4:文件服务承担,API 统一处理

方案4-文件服务承担,API 统一处理

response-filter-flow

优势:各个前端 和 各个后端服务 都不需要关注 何时需要生成可预览的 URL,何时 以及 如何生成 统一交给 API 网关处理。

劣势:API 网关 需要维护好 与 文件服务的调用关系,还需要分析每个请求的 response body 并修改 response body,这些操作处理起来都需要谨慎小心,做好充足的单元测试 和 API 测试,避免影响所有的 API 接口。

笔者在写这边文章的时候,就已经基于 spring cloud gateway 实现了方案 4,该方案确实特别方便,实现起来也没什么难度,不过需要前后端约定好保存到数据库的 file uri 的格式

总结

基于微服务架构风格,该问题 笔者已经总结了 4 种解决方案(真实情况远远不止 4 种),每种解决方案都有利弊,如果还有更好的解决方案,欢迎一起交流。

关注下面的标签,发现更多相似文章
评论