惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
月光博客
月光博客
T
Tailwind CSS Blog
阮一峰的网络日志
阮一峰的网络日志
小众软件
小众软件
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Last Week in AI
Last Week in AI
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
罗磊的独立博客
Jina AI
Jina AI
酷 壳 – CoolShell
酷 壳 – CoolShell
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 三生石上(FineUI控件)
量子位
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
美团技术团队
博客园 - 聂微东
V
V2EX

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派
突破系统限制,使用 Alfred Workflow + Pass 在任意登录表单...
2022-11-21 · via 少数派

Matrix 首页推荐 

Matrix 是少数派的写作社区,我们主张分享真实的产品体验,有实用价值的经验与思考。我们会不定期挑选 Matrix 最优质的文章,展示来自用户的最真实的体验和观点。 
文章代表作者个人观点,少数派仅对标题和排版略作修改。


最近一时兴起,又在从 1Password「逃离」。这次找到了一款在终端环境下运行的密码管理器 Pass,不仅开源免费,而且还能使用 PGP 算法进行加密,从各种角度来说,都是 1Password 不错的替代品。

话虽如此,单纯使用终端来管理密码始终不太方便。在几经研究之下,终于利用 Alfred 和 AppleScript 研究出可用于系统全域的自动填充系统(而不仅仅是在浏览器范围内)。

话不多说,先看疗效。

在这篇文章中,我会简单地描述如何利用 Pass 构建一个密码保险库,并尝试与 Alfred Workflow 连接起来,完成密码自动填充。

注:本文着重于讲解使用 Alfred Workflow 配合 Pass 快速填充密码,因此本节内容将会较为简略。你可以在互联网搜索相关资料获取更多教程。

要安装 Pass,叫出 macOS 用户的的老朋友 Homebrew 就行。

brew install pass

由于 Pass 不利用主密码、而是 GPG 密钥对来完成保险库加密,因此这个过程中会额外安装 GnuPG。对于大部分普通用户而言,我个人推荐再额外安装诸如 GPG Suite 的密钥管理工具。你可以前往 GPG Suite 的官网 下载到 GPG Suite。

安装好 GPG Suite 之后,打开 GPG Keychain 程序,你可以看到一些密钥展示在屏幕上。

GPG Suite 主界面

点击顶部「新建」按钮,然后填写你的姓名、电邮地址和一些额外信息。密码(Passphrase)可以不填(可以之后再设置),但如果你填写,建议你检查一下 pinentry-mac 是否被正确安装、并能正常在终端中使用(输入密钥时弹出对话框),否则使用 Alfred Workflow 的时候会卡住。你可以前往 pinentry-mac 的 Homebrew 页面 查看详情。

创建密钥后,在 GPG Keychain 中双击刚才创建好的密钥,找到「密匙标识」字符串,将它记录下来。

接下来,我们在终端输入以下指令来初始化 Pass 保险库。

pass init <key-id>

当然了,<key-id> 记得换成密匙标识,代表 Pass 需要用刚才新建的 PGP 密钥对来加密你的密码保险库。

接下来,利用 pass generate <account-description> 来创建密码,然后用 pass edit <account-description> 编辑它,以 login: <my-username> 的方式来写入用户名。

iTerm 窗口,执行 pass edit my-account,启动 vim 编辑器,在编辑模式下

你也可以利用官方提供的导入脚本,从 1Password 和其他密码管理器中直接将帐户信息导入到 Pass 中。你可以在 Pass 的官网 找到对应的脚本。

配置 Alfred Workflow

终于进入正题了。首先,我们确定一下需求:

  • 在 Alfred 中搜索帐户
  • 在终端中执行 pass <account>,然后解析 Pass 返回的结果
  • 自动输入用户名和密码

利用 Alfred 强大的 Workflow 功能,这些操作自然不是什么很复杂的事情。我们一个个拆开来说。

搜索 Pass 中的帐户

默认情况下,Pass 保险库中的帐户描述是不会加密、且保存为文件名,存储在 ~/.password-store 中。利用这一点,我们可以通过「查找文件」的方式来利用 Alfred 搜索保险库。

我利用 Node.js 包 alfy 配合 fs 来完成文件搜索工作。使用 Node.js 环境的原因主要有两个:一是我对 Node.js 比较熟悉、编写起来比较快;二是 Alfred 本身没有为 JavaScript 暴露文件搜索接口。

知道该怎么做,接下来就该动手开始做。打开 Alfred 偏好设置,进入「Workflows」界面,点击「Create a new workflow」按钮。

在弹出框中,可以只填写 Workflow 的名称。点击「Create」即可创建空白 Workflow。

点击右上角的「汉堡」菜单按钮呼出「组件库」(我就这么叫它了),找到「Script Filter」,然后把它拖出来。

拖出来之后,会弹出节点配置的对话框。Keyword 填写「pass」(或者其他你喜欢的呼出关键词)。在下面的脚本编辑框中,填入 ./node_modules/.bin/run-node searchquery.js "$1"

接下来,右键点击左侧 Workflow 列表中你刚才创建的 Workflow,选择「Open in Finder」。接下来打开终端,输入 cd (注意后面有个空格),然后将 Alfred 打开的文件夹拖进终端,回车。

2022-11-21 10.56.57

然后在终端中输入 npm init -y(啊,当然你的电脑得装一下 Node.js 环境,这里不展开了)。等屏幕滚完之后,输入 npm i alfy 来安装 alfy 包。

接着,在文件夹中新建 searchquery.js 文件,输入以下代码。

import alfy from "alfy"
import fs from "fs"

let { input } = alfy

// Search file in ~/.password-store
let files = fs.readdirSync(process.env.HOME + "/.password-store")

// filter file with input keyword
let inputLowercase = input.toLowerCase()
let filteredFiles = files.filter(file => file.toLowerCase().includes(inputLowercase))
for (let i in filteredFiles) {
	filteredFiles[i] = filteredFiles[i].replace(".gpg", "")
}

// output to alfred
alfy.output(filteredFiles.map(file => {
	return {
		title: file,
		subtitle: "Autofill username and password.",
		arg: file,
	}
}))

这段代码先将搜索目录设为你的主目录下的 .password-store 文件夹,然后将搜索词的小写版本和文件名的小写版本比较,如果文件名包括搜索关键词,那么就将它列出来,以 Alfred 可读取的列表形式输出。

注意,输出的列表中每一项 arg 变量,指的是当用户选中这个搜索结果之时,向下一个行为传递什么数据。此处我们选择将帐户名称完整输出至 Workflow 中的下一个节点。

保存文件,然后启动 Alfred Workflow。输入 pass <account>,如果能正常出现结果,那么证明你的配置和代码是正确无误的。

执行终端指令并解析结果

在终端中输入 pass <account>,你可以看到 Pass 会将密码写入到第一行,之后会用 key: value 的形式保存其他的账户信息。(至少大部分兼容 Pass 的密码管理器都会约定俗成地使用这样的格式。)

我们需要做的,就是在终端中执行这个指令,然后解析 Pass 返回的输出,接着传输到下一个操作中去。

在 Workflow 中,拖出一个 Run Script 节点。先关闭自动弹出的设置窗口,然后从上一个节点右侧牵出一条线,连接到这个节点的左侧。

还记得我们上一节提到的 arg 变量吗?这条连线意思就是,将用户点击的项目的 arg(在这里是帐户完整名称)传递给我们刚才新建的 Run Script 节点。

双击刚才新建的 Run Script 节点,在编辑框中输入以下代码。然后保存。

PATH=/opt/homebrew/bin:$PATH
pass "$1"

由于在一些程序中的终端环境与我们平常使用的终端环境有所差异,因此我们最好先将 Homebrew 的二进制包目录添加到环境变量中。接着,我们只需要平常地让 Pass 输出账户数据即可。

注意这里的 $1,它代表的是从上一个节点传入的变量。通过这样的操作,我们就可以让 Pass 输出账户详情,然后传递到下一个操作中去。

接着,我们再拖出一个 Run Script,将上一个 Run Script 节点连接到新建的 Run Script 节点。双击新建的 Run Script 节点,修改 Language 为「/usr/bin/osascript (JavaScript)」,然后写以下代码:

function run(argv) {
  let props = argv[0].split("\n")
  let password = props[0]
  let username = ""
  for (let i in props) {
    if (props[i].startsWith("login: ")) {
      username = props[i].split("login: ")[1]
    }
  }
  
  return `${username}\n${password}`
}

这段代码的意思就是,将 Pass 返回的数据以行折断,从第一行读取密码、从 login 字段读取用户名,然后将它们拼合,以换行符分割,再传递给下一个节点。

理论上,这两个段脚本可以合并成为一个 shell 脚本,但是 shell 写起来实在是不太直观…… 如果你感兴趣,你可以尝试一下。

自动填充

我们的最终目的,是将用户名和密码自动填充进输入框中。因此,我们需要利用 AppleScript 来完成这种高级自动化操作。

同样,拖出一个 Run Script 节点,把线连好。在新的 Run Script 设置中,将 Language 设为「/usr/bin/osascript (AppleScript)」,然后填写以下代码:

on run argv
  set theQuery to item 1 of argv
  set splitedArgv to paragraphs of theQuery
  tell application "System Events"
    repeat with theItem in splitedArgv
      keystroke theItem
      key code 48
    end repeat
  end tell
end run

这段代码的意思是,从 Alfred 提供的变量中拿到我们传递过去的用户名与密码组合,将它们按行折断,形成数组。之后告诉「System Events」,对于这个数组中的每一项都进行键盘输入、然后按下 Tab 按键(48 号按键)以跳转到下一个输入框继续输入。

至此,我们的 Alfred Workflow 就这样编写完成了。你可以尝试在浏览器或者其他 app 中,呼出 Alfred 并尝试使用这个 Workflow。

抛砖引玉

很明显,单纯使用这个 Alfred Workflow 自然有其限制:例如,遇到 Grammarly 或者 Apple 官网那种用户名密码分步骤填写的网站,这个 Workflow 自然也就无能为力。以及,OTP 密码的复制方法并没有在本文中列出。

不过,这篇文章姑且为你提供了编写类似的 Workflow 的方法,你可以尝试自己创建、自己改造这个 Workflow。

当然,如果你希望使用开箱即用的版本,你可以尝试我制作好的文件,你可以 前往 GitHub 项目主页 下载到。(下载完别忘记点一个 star!)

另外,如果你没有购买 Alfred Powerpack,也可以使用快捷指令作为「平替」。快捷指令 app 中,包括字符串处理和 AppleScript 都有对应的执行方式,感兴趣的也可以尝试自己制作。

> 少数派请你做地图:城市声音收藏夹火热征集中,期待你创作的城市之声 🎧 

> 下载少数派 2.0 客户端 、关注少数派公众号,解锁全新阅读体验 📰 

> 实用、好用的正版软件,少数派为你呈现 🚀