隐藏密码重置页面的本机管理命令

This commit is contained in:
xuans 2026-10-01 20:10:32 +08:00
parent 83b1f44fdc
commit f8db6ce4b1
5 changed files with 22 additions and 30 deletions

View File

@ -49,7 +49,7 @@ func (s *Server) resolvePasswordResetAccount(c *gin.Context) {
AccountType: "super_admin",
AccountLabel: "超级管理员",
Title: "超级管理员密码重置",
Description: "已识别为超级管理员账户。超级管理员不能通过普通重置页面修改密码,请使用 Scert-admin 开启的一次性重置入口。",
Description: "已识别为超级管理员账户。该账户不能通过普通重置页面修改密码,请联系系统管理员按照服务器本机安全维护流程处理。",
Action: "local_admin_command",
})
return

View File

@ -31,7 +31,10 @@ func TestPasswordResetResolutionOnlyOffersLocalAdminCommand(t *testing.T) {
t.Fatal(err)
}
if payload["account_type"] != "super_admin" || payload["action"] != "local_admin_command" {
t.Fatalf("超级管理员没有返回本机命令指引:%v", payload)
t.Fatalf("超级管理员没有返回受控本机处理标识:%v", payload)
}
if description, _ := payload["description"].(string); strings.Contains(strings.ToLower(description), "scert-admin") || strings.Contains(description, "systemctl") {
t.Fatalf("公开查询不应泄露本机管理命令:%s", description)
}
for _, field := range []string{"reset_path", "reset_url", "token", "nonce"} {
if _, exists := payload[field]; exists {

View File

@ -40,24 +40,23 @@ test("超级管理员查询保留本机处理标识,不生成网页重置链
assert.equal(state.resolution.value, null);
});
test("本机命令指引仅对接口明确标记的处理方式显示", () => {
test("密码重置页面不显示本机管理命令", () => {
const root = template("./PasswordReset.vue");
const guides = elements(root, (node) => node.tag === "LocalResetGuide");
assert.equal(guides.length, 1);
assert.equal(guides[0].props.find((prop) => prop.name === "if").exp.content,
"resolution.action === 'local_admin_command'");
assert.equal(guides.length, 0);
const source = readFileSync(new URL("./PasswordReset.vue", import.meta.url), "utf8");
assert.doesNotMatch(source, /systemctl|scert-admin|本机管理命令/iu);
const message = elements(root, (node) => node.tag === "p"
&& node.props.some((prop) => prop.name === "if"
&& prop.exp?.content === "message && !resolution"));
assert.equal(message.length, 1);
});
test("本机指引只显示固定命令,解释放入悬浮提示", () => {
test("本机指引不包含可执行命令", () => {
const root = template("../components/LocalResetGuide/LocalResetGuide.vue");
assert.equal(elements(root, (node) => ["a", "input", "form"].includes(node.tag)).length, 0);
assert.equal(elements(root, (node) => node.tag === "HelpTip").length, 1);
const commands = elements(root, (node) => node.tag === "code")
.map((node) => node.children.filter((child) => child.type === 2)
.map((child) => child.content).join(""));
assert.deepEqual(commands, ["systemctl start Scert-admin", ".\\scert-admin.exe"]);
});
assert.equal(elements(root, (node) => node.tag === "code").length, 0);
const source = readFileSync(new URL("../components/LocalResetGuide/LocalResetGuide.vue", import.meta.url), "utf8");
assert.doesNotMatch(source, /systemctl|scert-admin|<code/iu);
});

View File

@ -1,6 +1,5 @@
<script setup>
import AccessShell from "../components/AccessShell/AccessShell.vue";
import LocalResetGuide from "../components/LocalResetGuide/LocalResetGuide.vue";
import { usePasswordReset } from "./PasswordReset.js";
const {
@ -55,7 +54,6 @@ const {
<span class="reset-resolution-label">处理方式</span>
<strong>{{ resolution.title }}</strong>
<p>{{ resolution.description }}</p>
<LocalResetGuide v-if="resolution.action === 'local_admin_command'" />
<a
v-if="resolution.reset_path"
class="access-submit reset-entry-link"
@ -83,4 +81,4 @@ const {
</AccessShell>
</template>
<style src="./PasswordReset.css"></style>
<style src="./PasswordReset.css"></style>

View File

@ -5,24 +5,16 @@ import HelpTip from "../HelpTip/HelpTip.vue";
<template>
<section class="local-reset-guide">
<div class="local-reset-guide__heading">
<span>本机管理命令</span>
<span>本机安全维护</span>
<HelpTip>
请由部署管理员在 Scert 所在主机执行命令。Linux 使用 root 终端;
Windows 使用提升权限的控制台,在安装目录运行。
验证码和新密码仅在本机终端输入,本页面不会开启重置会话。
请联系部署管理员按照服务器本机安全维护流程处理。
页面不会显示或接收维护命令、验证码和新密码。
</HelpTip>
</div>
<dl class="local-reset-guide__commands">
<div>
<dt>Linux</dt>
<dd><code>systemctl start Scert-admin</code></dd>
</div>
<div>
<dt>Windows</dt>
<dd><code>.\scert-admin.exe</code></dd>
</div>
</dl>
<p class="local-reset-guide__message">
该账户需要由系统管理员在服务器本机完成安全维护流程。
</p>
</section>
</template>
<style scoped src="./LocalResetGuide.css"></style>
<style scoped src="./LocalResetGuide.css"></style>