“在线剪贴板”服务开发实录——逃不过的霍夫施塔特定律

哈德韦

共 2024字,需浏览 5分钟

 ·

2022-06-12 13:07

昨天的视频《扫二维码登录一定安全吗?》里,现场演示了通过截获网站 Cookie 的方式,可以轻易盗用别人的账号。其中有个环节,盗取的 Cookie 是手动获取的,要改进成自动上传是很容易的。比如在设置 Cookie 到 LocalStorage 的同时,上传保存到服务器,然后再自动粘贴到目标网站进行用户身份顶替。所以做为用户,要千万当心,不要随便扫描二维码(确认是官方的才行)。


在线剪贴板
在红客思维状态下,提醒完用户小心后,我又切换回开发者的思维,认识到在一个客户端将复制的内容保存到云端,然后在另一端取出云端保存的内容,然后进行粘贴的这一场景,其实是很有应用价值的。只要用途正当,可以非常方便用户的日常工作和生活。是的,这其实就是“跨设备拷贝”。

用过 iPhone 和 Mac 的同学很熟悉,只要在手机和电脑上都登录同一个 Apple ID,那么,在手机上拷贝的内容,可以直接在电脑上粘贴,反之亦然。不仅是文字,图片也可以。(还不知道的同学赶紧试一下,别再用微信文件助手了,根本用不着那么麻烦!)

但遗憾的是,如果你用 iPhone,再用 Windows 电脑,就享受不到自带的“跨设备拷贝”的便利性了,在这样的情况下,还是得用微信文件助手。

如果要共享 iPhone 和 Windows 这样的不同厂商的设备的剪贴板,就得有个“在线剪贴板”这个的服务,然后在端上安装相关的应用,能够和这个“在线剪贴板”打交道。我一搜,“在线剪贴板”应用数不胜数,看来果然是一个很有价值的应用,已经是一片红海。看了好几个动态返回 ID(key) 的实现后,找到了一个可以指定 ID(key)的实现,这个最方便实现“跨设备拷贝”功能。把玩了一下人家开发好的,虽然完全符合我的使用需求,但却是一个国外站点,不太方便直接拿来使用(比如微信小程序的后端服务域名,不仅需要设置白名单,还需要 ICP 备案才行)。

于是我决定自己实现一个。只需要两个接口,一个保存,一个读取即可,为了快速整完,可以在我的万能 BFF 项目里迭代添加这两个接口。

一顿操作猛如虎,部署一个万能 BFF

霍夫施塔特定律
你觉得完成两个接口需要多久?我一拍脑袋,20 分钟!我信心满满地开始写起来,觉得甚至可能 10 分钟就能搞定!为了计时,我将写代码的全过程录制下来了,最后被啪啪打脸,从开始写,到最后发布成功,花了足足 2 个小时!!

果然是逃不过著名的霍夫施塔特定律呀,这个定律很有意思,它是说:

即使你考虑到了霍夫施塔特定律,项目的实际完成时间总是比预期的要长。

这是一个递归的说法。这个定律就是说,项目的实际完成时间总是比预期的要长,哪怕你已经提前考虑到了这一点,预留了“足够”的 Buffer 时间,然而到最后那点儿时间还是不够!

GraphQL

本服务提供了两个 GraphQL 接口,在视频里,穿插讲解了 GraphQL 设备指南。这个设计指南很早就写了,详见:
GraphQL API 设计指南

另外,后来为了演讲专门做了一个演示文稿,借此机会也分享一下:

GraphQL API Design

https://reveal.inversify.cn/



TDD
开发的时候,我还是想着要使用 TDD 的,实际上也使用了,不过步子迈得不够小,算是糙版的 TDD 。

最终成果

实现了支持文本内容的“在线剪贴板”,可以通过 cURL 体验一把:

# 复制内容到剪贴板curl --request POST \    --header 'content-type: application/json' \    --url 'https://sls.pa-ca.me/nest/graphql' \    --data '{"query":"mutation CopyToClipboard($clipboard: ClipboardInput!) {\n  copyToClipboard(clipboard: $clipboard) {\n    key\n    value\n  }\n}","variables":{"clipboard":{"key":"test2","value":"UniHeart2"}}}'        # 读取剪贴板内容curl --request POST \    --header 'content-type: application/json' \    --url 'https://sls.pa-ca.me/nest/graphql' \    --data '{"query":"query Clipboard($key: String!) {\n  clipboard(key: $key) {\n    key\n    value\n  }\n}","variables":{"key":"test"}}'


开发实录

浏览 64
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报