# DCAuth 客户端 三个系统共用的设备认证客户端,通过 `dcauth://` 协议被浏览器唤起。 ## 运行方式 - **Windows**:GUI 常驻程序。启动后进入系统托盘,通过协议唤起时只出现一个登录确认窗口;成功后在托盘气泡中提示,不再连续弹多个消息框。 - **macOS**:`DCAuth.app` 注册 `dcauth://`,浏览器可直接唤起;内部是后台常驻进程 + 系统图形确认框,重复唤起会转发给已有进程,不会叠加实例。 ## 构建 Windows x64: ```bash cd apps/dcauth x86_64-w64-mingw32-windres --codepage=65001 versioninfo.rc \ -O coff -o versioninfo_windows_amd64.syso CGO_ENABLED=0 GOOS=windows GOARCH=amd64 \ go build -trimpath -ldflags "-H windowsgui -s -w" \ -o dist/DCAuth.exe . cp dist/DCAuth.exe dist/DCAuth-2.0.1.exe ``` 版本号统一在 `main.go` 的 `clientVersion` 和 `versioninfo.rc` 中维护。`DCAuth.exe` 右键“属性 → 详细信息”会显示文件版本 `2.0.1.0` 和产品版本 `2.0.1`,托盘菜单、设备信息及确认窗口也会显示当前版本。 Windows ARM64: ```bash CGO_ENABLED=0 GOOS=windows GOARCH=arm64 \ go build -trimpath -ldflags "-H windowsgui -s -w" \ -o dist/DCAuth-arm64.exe . ``` macOS 通用二进制: ```bash CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 \ go build -trimpath -ldflags "-s -w" -o /tmp/DCAuth-macos-arm64 . CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 \ go build -trimpath -ldflags "-s -w" -o /tmp/DCAuth-macos-amd64 . lipo -create -output dist/DCAuth-macos \ /tmp/DCAuth-macos-arm64 /tmp/DCAuth-macos-amd64 chmod +x dist/DCAuth-macos codesign --force --sign - dist/DCAuth-macos ``` ## Windows 首次运行 直接运行一次 `DCAuth.exe`: - 注册 `dcauth://` 协议到当前 Windows 用户。 - 生成 Ed25519 设备密钥,使用 Windows DPAPI 加密保存在 `%LOCALAPPDATA%\DCAuth\device.key`。 - 进入系统托盘后台运行,不弹设备信息窗口。 托盘操作: - 双击图标:查看设备码并复制到剪贴板。 - 右键菜单:查看设备码、退出 DCAuth。 - 浏览器登录:只弹出一个确认窗口;点击“确定”后显示成功气泡,点击“取消”则拒绝。 - 再次唤起协议:第二个进程会把请求转交给常驻进程,然后立即退出。 ## macOS 安装(一次性) ```bash cd apps/dcauth ./build-macos.sh # 默认装到 ~/Applications/DCAuth.app ``` 脚本会做四件事: 1. 用 `go build` 产出当前架构的二进制(自动读取 `main.go` 的 `clientVersion`)。 2. 用 `osacompile` 生成 AppleScript 壳,把 `dcauth://` 事件转成 argv 交给二进制。 3. 向 LaunchServices 注册 `dcauth://` 协议,并做 ad-hoc 签名。 4. 打印安装路径与退出方式。 装好之后浏览器登录页点一次即可直接唤起确认框,和 Windows 一样,**不再需要命令行**。 - 查看设备码:`open "$HOME/Applications/DCAuth.app"` - 停止后台进程:`"$HOME/Applications/DCAuth.app/Contents/Resources/dcauth" --exit` - 换成 Apple 芯片 / Intel 通用包:脚本在目标机器上各跑一次即可(二进制与架构绑定)。 > 为什么要套一层 AppleScript:macOS 只把自定义协议 URL 作为 Apple Event 投递, > 纯 Go 的命令行程序收不到(实测进程参数为空)。AppleScript applet 的 > `on open location` 是目前不引入 Cocoa/cgo 的最稳做法。 ## macOS 命令行方式(备用) 没有安装 `.app` 时,也可以直接执行二进制: 登录页在开发模式会显示一条 `dcauth://...` 链接。复制后在终端执行: ```bash cd apps/dcauth ./dist/DCAuth-macos "dcauth://authorize?app=order_site&challenge_id=...&challenge=...&api=http%3A%2F%2Flocalhost" ``` 首次执行会启动后台进程并显示图形确认框;命令本身会立即返回。后续协议请求会转发给这个后台进程。 停止后台进程: ```bash ./dist/DCAuth-macos --exit ``` macOS 当前仍是开发版:私钥明文保存在 `~/Library/Application Support/DCAuth/device.key`(没有 DPAPI 等系统级保护),不要把这一版当成生产级凭证。安装 `DCAuth.app` 后浏览器可以自动唤起,但密钥保护强度仍低于 Windows。 如果只是测后台业务,不想每次都走短信和设备验证,可以在“后台用户”里把测试账号设为 **技术测试**。该账号只使用账号密码登录;正式账号仍必须走短信 + DCAuth。 ## 浏览器联动 登录页创建 challenge 后跳转: ```text dcauth://authorize?app=order_site&challenge_id=...&challenge=...&api=https%3A%2F%2Fks.khhao.com ``` 客户端校验 app 和 api 白名单后,弹出一次确认框,签名并提交到: ```text POST /api/dcauth/authorize ``` 浏览器轮询 challenge 状态,拿到一次性 ticket 后完成登录。 ## 支持的应用 | app | 生产入口 | |---|---| | `order_site` | `https://ks.khhao.com`(历史入口 `https://order.khhao.com` 仍放行) | | `live_hub` | `https://live.khhao.com` | | `affiliate_dash` | `https://skin.khhao.com` | 本地开发入口已内置在 `main.go` 的 `appRegistry` 中,包括 `http://localhost`、`http://localhost/`、`http://127.0.0.1`、`http://192.168.10.6` 及对应 Vite 端口。 ## 验证 ```bash go test ./... CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags "-H windowsgui -s -w" -o dist/DCAuth.exe . ``` ## 安全说明 - 私钥不离开本机,Windows 使用 DPAPI 保护。 - 服务端只保存设备公钥和设备码,不采集或保存硬件序列号。 - 设备码只由公钥派生,不包含硬件指纹;更换硬件不会改变设备码。 - 正式分发前建议使用代码签名证书,避免 SmartScreen 和杀毒软件误报。 - 如果要做到 token 也不能复制,需要后续让 exe 对每次 API 请求签名,或把 exe 作为唯一客户端。