为了账号安全,请及时绑定邮箱和手机立即绑定

安全文件分享 —— 在线分享敏感文件的更安全方式

这是我为The Pinata Challenge提交的作品。

我建的

我开发了“Secure File Share(安全文件共享)”,这是一个开源的、可自行托管的文件共享解决方案,旨在满足数字世界中常见的需求:在不依赖第三方服务的情况下安全地分享敏感文件。

灵感来源

作为一个开发人员,与远程团队合作时,我们经常需要在网上分享公司的敏感文件,这有不小心泄露给外界的风险。文件散落在电子邮件附件、我们交流的任何地方。目前,我们采用了Google Drive的具有密码保护功能的文件分享,但我们始终在寻找不涉及任何第三方,并且我们可以完全掌控文件的解决方案,特别是如果能自建的话。我们的DevOps同事正在研究解决方案,但如果由我来构建这个解决方案,我会把它想象成这样。

这也深受Onetimesecret的影响。它就像是为文件设计的一次性秘密服务。

它是怎样工作的
  1. 上传你想要分享的文件
  2. 设置密码和过期时间,然后点击创建共享链接按钮
  3. 将共享链接发送给你要分享的人。建议单独发送密码。

上传的文件及其相关的记录将在指定的到期日期被删除。当你查看文件时,设定的到期时间将被覆盖,文件将被设置为在消失前的5分钟内有效。

安全文件传输包括以下几个主要特点:

  1. 一次性且带密码保护的分享链接
  2. 无需注册。
  3. 完全自托管
演示

快速一览

英雄图片

上传页

分享页

文件查看页面

文件查看页面

我的程序

注意:您可以在README中了解更多详情)

技术堆栈:

  • 后端:Express.js(使用 TypeScript)
  • 前端:EJS 模板,Bulma CSS 框架,Alpine.js
  • 数据库:使用 Prisma ORM 的 SQLite(如有需要,可轻松替换为其他数据库)
  • 文件存储:Pinata 云
  • 后台处理:使用 Redis 的 BullMQ

我选择技术栈时尽量保持轻量,力求不过度设计。具体来说,我使用了以下技术:一个简单的 Express TS 后端,ejs 模板搭配了 Alpine.js(用于最小的前端交互)和 Bulma 作为 CSS 框架。数据库只是一个 sqlite 文件,因为对于这个黑客松项目来说,不需要一个完整的数据库,但可以通过修改 datasource 来轻松更改。我使用 BullMQ 和 Redis 来处理后台任务(如文件过期)。当然,还包括 Pinata 云。我将此部署在 fly.io,因为它们提供了一个慷慨的免费套餐,但也可以部署在其他地方,比如 VPS(可以使用提供的 docker compose 文件)。

更多细节

Pinata 在这个项目中起着关键作用,所有共享文件都需要存储,这就需要 Pinata 来存储这些文件。

这里是我主要通过Files SDK操作Pinata的这个myPinata.ts文件,主要用于操作。

    import { FileObject, PinataSDK } from "pinata";
    import dotenv from "dotenv";

    dotenv.config();

    const pinata = new PinataSDK({
        pinataJwt: process.env.PINATA_JWT,
        pinataGateway: process.env.PINATA_GATEWAY
    });

    export async function 上传文件(file: FileObject) {
        try {
            const upload = await pinata.upload.file(file);
            return upload;
        } catch (error) {
            console.error(error);
        }
    }

    export async function 获取文件URL(cid: string, expires=1800) {
        try {
            const signedUrl = await pinata.gateways.createSignedURL({
                cid,
                expires // 默认为30分钟(1800秒,即半小时)
            });
            return signedUrl;
        } catch (error) {
            console.error(error);
        }
    }

    export async function 删除文件(fileId: string) {
        try {
            const deleted = await pinata.files.delete([fileId]);
            return deleted;
        } catch (error) {
            console.error(error);
        }
    }

全屏模式(点击进入/退出)

点击全屏按钮进入全屏模式,再次点击退出

我在我端点处理器中使用这三个功能来处理与Pinata相关的文件操作。我的后台任务也会使用deleteFile函数,因为这些后台任务会在文件到期时自动分发删除任务。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消