feat: 内部署名改为编译期注入(构建机本地文件,不进仓库);关于页展示

This commit is contained in:
AskaEth committed 2026-09-09 20:07:59 +08:00
1 parent d288e2bb22
commit 76e725ca96
6 files changed
+66 -1

No files matched your search

+3
View File
@@ -11,6 +11,9 @@ data/
rules/*
!rules/README.md
# 内部署名(构建期注入,绝不进仓库)
deploy/signature.local.txt
# 开发文档(内部设计文档,不进仓库)
devdocs/
+11 -1
View File
@@ -30,7 +30,17 @@ cd ..
echo === [3/5] server build ===
cd server
if not exist ..\dist mkdir ..\dist
go build -o ..\dist\scoreboard.exe . || exit /b 1
REM 内部署名从构建机本地文件注入(deploy\signature.local.txt 已 gitignore,不进公开仓库);
REM 文件不存在时二进制里也是空的,源码永远不含真实署名。
set "INTERNAL_SIGNATURE="
if exist "..\deploy\signature.local.txt" set /p INTERNAL_SIGNATURE=<"..\deploy\signature.local.txt"
if defined INTERNAL_SIGNATURE (
go build -ldflags "-X git.yeij.top/AskaEth/Scoreboard/server/internal/version.InternalSignature=%INTERNAL_SIGNATURE%" -o ..\dist\scoreboard.exe . || exit /b 1
echo internal signature injected
) else (
go build -o ..\dist\scoreboard.exe . || exit /b 1
echo no internal signature
)
cd ..
echo === [4/5] console deps ===
@@ -0,0 +1,20 @@
package httpapi
import (
"net/http"
"git.yeij.top/AskaEth/Scoreboard/server/internal/auth"
"git.yeij.top/AskaEth/Scoreboard/server/internal/version"
)
// systemRoutes 挂载系统级只读信息。
func (s *server) systemRoutes(mux *http.ServeMux) {
// 内部署名是编译期注入的,不暴露给匿名访客:至少要登录(recorder 及以上)才能读到
mux.HandleFunc("GET /api/system/about", s.read(auth.RoleRecorder, s.systemAbout))
}
func (s *server) systemAbout(w http.ResponseWriter, r *http.Request) (any, error) {
return map[string]any{
"internalSignature": version.InternalSignature,
}, nil
}
+1
View File
@@ -76,6 +76,7 @@ func New(opts Options) http.Handler {
s.routes(mux)
s.exportRoutes(mux)
s.rulesRoutes(mux)
s.systemRoutes(mux)
if opts.WS != nil {
mux.Handle("/ws", opts.WS)
}
+11
View File
@@ -0,0 +1,11 @@
// Package version 保存构建期注入的版本与署名信息。
package version
// Version 由构建脚本注入:-ldflags "-X .../version.Version=..."
var Version = "dev"
// InternalSignature 是内部署名,**由构建机本地文件注入**,编译期写进二进制。
//
// 源码里必须永远保持为空字符串:真实署名只存在于构建机的 deploy/signature.local.txt
// (该文件已 gitignore),因此公开仓库里既没有值、也改不动它。
var InternalSignature = ""
+20
View File
@@ -72,6 +72,9 @@ const port = computed(() => {
const origin = computed(() => window.location.origin)
// 内部署名由构建期注入,只有登录后(recorder+)才拿得到;未注入时为空串
const internalSignature = ref('')
onMounted(async () => {
// 直接从 /api/health 取版本;不走 adminApi.health 的示例数据兜底,避免把 mock 当成真实版本
try {
@@ -83,6 +86,16 @@ onMounted(async () => {
versionChecked.value = true
}
try {
const res = await fetch('/api/system/about', { credentials: 'include' })
if (res.ok) {
const body = (await res.json()) as { ok: boolean; data?: { internalSignature?: string } }
internalSignature.value = body.data?.internalSignature ?? ''
}
} catch {
// 未登录 / 接口不可达都按「没有署名」处理,不打扰用户
}
if (!data.loaded) void data.load()
})
</script>
@@ -99,6 +112,13 @@ onMounted(async () => {
</div>
</div>
<div v-if="internalSignature" class="mx-card" style="margin-bottom: 16px">
<div class="mx-card-body" style="display: flex; flex-direction: column; gap: 4px">
<span style="font-size: 12px; color: var(--mx-t3)">内部署名</span>
<strong style="font-size: 15px">{{ internalSignature }}</strong>
</div>
</div>
<section class="mx-card">
<div class="mx-card-head">
<span class="mx-card-title">基本信息</span>