feat(dcauth): 移除机器码,改用纯设备码认证
- DCAuth 协议升级到 v2,签名原文只含设备码;客户端 2.0.0,旧版本返回 426 - 删除客户端机器码采集、后端 machine_code_* 字段与日志、后台机器码展示 - 102 迁移在生产执行前直接改为无机器码结构;SQL 守卫仅放行该文件 - Mock 短信不启用每日限额;修复慢电脑首次启动的协议转发竞态 - 新增 macOS DCAuth.app 打包脚本,注册 dcauth:// 协议,浏览器可直接唤起
This commit is contained in:
+46
-25
@@ -191,6 +191,7 @@ var (
|
||||
trayData notifyIconData
|
||||
trayAdded bool
|
||||
runtimeIdentity identity
|
||||
identityReady bool
|
||||
authorizationActive bool
|
||||
windowProcedure = syscall.NewCallback(dcauthWindowProc)
|
||||
)
|
||||
@@ -209,16 +210,14 @@ func runClient(protocolArg string) {
|
||||
if forwardToRunningInstance(protocolArg) {
|
||||
return
|
||||
}
|
||||
showError("DCAuth 启动失败", "已有 DCAuth 实例正在启动,但暂时无法连接,请稍后重试。")
|
||||
return
|
||||
firstInstance, err = acquireSingleInstance()
|
||||
if err != nil || !firstInstance {
|
||||
showError("DCAuth 启动失败", "DCAuth 已在运行但暂时没有响应。请在任务管理器中结束 DCAuth.exe 后重试。")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
registerProtocol()
|
||||
runtimeIdentity, err = loadOrCreateIdentity()
|
||||
if err != nil {
|
||||
showError("DCAuth 初始化失败", err.Error())
|
||||
return
|
||||
}
|
||||
if err := createHiddenWindow(); err != nil {
|
||||
showError("DCAuth 启动失败", err.Error())
|
||||
return
|
||||
@@ -228,10 +227,20 @@ func runClient(protocolArg string) {
|
||||
return
|
||||
}
|
||||
|
||||
runtimeIdentity, err = loadOrCreateIdentity()
|
||||
if err != nil {
|
||||
removeTrayIcon()
|
||||
showError("DCAuth 初始化失败", err.Error())
|
||||
destroyWindow.Call(mainWindow)
|
||||
mainWindow = 0
|
||||
return
|
||||
}
|
||||
identityReady = true
|
||||
|
||||
if protocolArg != "" {
|
||||
handleAuthorization(protocolArg)
|
||||
} else {
|
||||
showTrayBalloon("DCAuth v"+clientVersion+" 已在后台运行", "双击托盘图标可查看版本、设备码和机器码。")
|
||||
showTrayBalloon("DCAuth v"+clientVersion+" 已在后台运行", "双击托盘图标可查看版本和设备码。")
|
||||
}
|
||||
|
||||
runMessageLoop()
|
||||
@@ -279,16 +288,16 @@ func acquireNamedMutex(name string) (uintptr, bool, error) {
|
||||
}
|
||||
|
||||
func forwardToRunningInstance(protocolArg string) bool {
|
||||
for attempt := 0; attempt < 100; attempt++ {
|
||||
if postToRunningInstance(protocolArg) {
|
||||
return true
|
||||
for attempt := 0; attempt < 300; attempt++ {
|
||||
if hwnd := findRunningInstanceWindow(); hwnd != 0 {
|
||||
return sendToRunningInstance(hwnd, protocolArg)
|
||||
}
|
||||
sleep.Call(100)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func postToRunningInstance(protocolArg string) bool {
|
||||
func findRunningInstanceWindow() uintptr {
|
||||
classPtr, _ := syscall.UTF16PtrFromString(windowClassName)
|
||||
titlePtr, _ := syscall.UTF16PtrFromString(windowTitle)
|
||||
hwnd, _, _ := findWindowW.Call(
|
||||
@@ -297,12 +306,13 @@ func postToRunningInstance(protocolArg string) bool {
|
||||
)
|
||||
runtime.KeepAlive(classPtr)
|
||||
runtime.KeepAlive(titlePtr)
|
||||
if hwnd == 0 {
|
||||
return false
|
||||
}
|
||||
return hwnd
|
||||
}
|
||||
|
||||
func sendToRunningInstance(hwnd uintptr, protocolArg string) bool {
|
||||
if protocolArg == "" {
|
||||
postMessageW.Call(hwnd, showWindowMessage, 0, 0)
|
||||
return true
|
||||
result, _, _ := postMessageW.Call(hwnd, showWindowMessage, 0, 0)
|
||||
return result != 0
|
||||
}
|
||||
|
||||
encoded, _ := syscall.UTF16FromString(protocolArg)
|
||||
@@ -387,6 +397,9 @@ func runMessageLoop() {
|
||||
func dcauthWindowProc(hwnd, msg, wParam, lParam uintptr) uintptr {
|
||||
switch uint32(msg) {
|
||||
case wmCopyData:
|
||||
if !identityReady {
|
||||
return 0
|
||||
}
|
||||
data := (*copyDataStruct)(unsafe.Pointer(lParam))
|
||||
if data != nil && data.DwData == copyDataMagic && data.CbData > 0 && data.LpData != 0 {
|
||||
count := int(data.CbData / 2)
|
||||
@@ -396,12 +409,18 @@ func dcauthWindowProc(hwnd, msg, wParam, lParam uintptr) uintptr {
|
||||
}
|
||||
return 0
|
||||
case showWindowMessage:
|
||||
showDeviceInfo()
|
||||
if identityReady {
|
||||
showDeviceInfo()
|
||||
}
|
||||
return 0
|
||||
case trayCallbackMessage:
|
||||
switch uint32(lParam) {
|
||||
case wmLButtonDblClk:
|
||||
showDeviceInfo()
|
||||
if identityReady {
|
||||
showDeviceInfo()
|
||||
} else {
|
||||
showTrayBalloon("DCAuth 正在初始化", "设备信息准备完成后即可查看。")
|
||||
}
|
||||
case wmRButtonUp, wmContextMenu:
|
||||
showTrayMenu(hwnd)
|
||||
}
|
||||
@@ -497,7 +516,11 @@ func showTrayMenu(hwnd uintptr) {
|
||||
|
||||
switch command {
|
||||
case trayMenuDeviceInfo:
|
||||
showDeviceInfo()
|
||||
if identityReady {
|
||||
showDeviceInfo()
|
||||
} else {
|
||||
showTrayBalloon("DCAuth 正在初始化", "设备信息准备完成后即可查看。")
|
||||
}
|
||||
case trayMenuExit:
|
||||
destroyWindow.Call(hwnd)
|
||||
}
|
||||
@@ -505,12 +528,11 @@ func showTrayMenu(hwnd uintptr) {
|
||||
|
||||
func showDeviceInfo() {
|
||||
text := fmt.Sprintf(
|
||||
"版本:v%s\n\n设备码:%s\n机器码:%s\n\nDCAuth 正在后台运行。浏览器登录时只会打开一个确认窗口。\n设备码和机器码已复制到剪贴板。",
|
||||
"版本:v%s\n\n设备码:%s\n\nDCAuth 正在后台运行。浏览器登录时只会打开一个确认窗口。\n设备码已复制到剪贴板。",
|
||||
clientVersion,
|
||||
runtimeIdentity.deviceID,
|
||||
runtimeIdentity.machineCode,
|
||||
)
|
||||
copyToClipboard(runtimeIdentity.deviceID + "\n" + runtimeIdentity.machineCode)
|
||||
copyToClipboard(runtimeIdentity.deviceID)
|
||||
showInfo("DCAuth v"+clientVersion+" 设备信息", text)
|
||||
}
|
||||
|
||||
@@ -543,11 +565,10 @@ func handleAuthorization(raw string) {
|
||||
if !confirm(
|
||||
"DCAuth v"+clientVersion+" · "+app.DisplayName+" 本机登录确认",
|
||||
fmt.Sprintf(
|
||||
"是否允许使用本机设备登录「%s」?\n\n客户端版本:v%s\n设备码:%s\n机器码:%s\n\n点击“确定”允许本次登录,点击“取消”拒绝。",
|
||||
"是否允许使用本机设备登录「%s」?\n\n客户端版本:v%s\n设备码:%s\n\n点击“确定”允许本次登录,点击“取消”拒绝。",
|
||||
app.DisplayName,
|
||||
clientVersion,
|
||||
runtimeIdentity.deviceID,
|
||||
runtimeIdentity.machineCode,
|
||||
),
|
||||
) {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user