fix(auth): 激活页清除残留登录态 + 全站密码框显式 autocomplete 语义

R61/R62:两个独立缺陷(测试人员反馈「设置密码框已有 123456 + 激活后直接进管理后台」)。

① 激活后进管理后台 —— 安全缺陷(公用电脑 = 越权)
Activate.vue 激活成功与「返回登录」都跳 /login,而 router guard
(router/index.js:203-222)见到 isLoggedIn && role==='admin' 会重定向到 /admin。
浏览器残留 admin 登录态时(测试人员刚用 admin 操作过后台),考生会被
直接送进管理后台;且 /api/admin/* 全部挂 adminAuth(router.js:25)
⇒ 残留 token 有效时管理接口真能调。
修法:激活页按「未登录」语义处理 —— onMounted 与激活成功后均 clearAuth()。

② 设置密码页密码框被浏览器预填
密码框未显式声明 autocomplete,而 EP el-input 该 prop 默认 "off",
Chromium 对 type=password 会忽略 off,改用该站点已保存凭据自动填充。
密码规则仅 min:6 ⇒ "123456" 恰好合法 ⇒ 用户不知情下即把密码设成 123456。
修法:6 个密码框显式声明语义 —— 设密码/重置密码 new-password(4 处),
登录 current-password(2 处,含管理员 tab)。

验证:真浏览器 21/21 断言通过(含「残留 admin 态直接访问 /login 必跳 /admin」
对照臂,证明断言非恒真);TDZ 扫描 PASS(26 文件);权威脚本构建
157 文件 / 70 .gz;生产零中断上线(MainPID/NRestarts/ActiveEnterTimestamp 未变)。
This commit is contained in:
2026-09-30 11:39:53 +08:00
parent ef32d30a57
commit a47e823277
3 changed files with 18 additions and 0 deletions

View File

@@ -149,6 +149,7 @@
<el-input <el-input
v-model="step3Form.password" v-model="step3Form.password"
type="password" type="password"
autocomplete="new-password"
placeholder="请设置登录密码(至少6位)" placeholder="请设置登录密码(至少6位)"
size="large" size="large"
show-password show-password
@@ -159,6 +160,7 @@
<el-input <el-input
v-model="step3Form.confirmPassword" v-model="step3Form.confirmPassword"
type="password" type="password"
autocomplete="new-password"
placeholder="请再次输入密码" placeholder="请再次输入密码"
size="large" size="large"
show-password show-password
@@ -211,8 +213,14 @@ import { ElMessage } from 'element-plus'
import { ArrowLeft, HomeFilled, Refresh } from '@element-plus/icons-vue' import { ArrowLeft, HomeFilled, Refresh } from '@element-plus/icons-vue'
import * as authApi from '@/api/auth' import * as authApi from '@/api/auth'
import { showTestSmsCode } from '@/utils/testSms' import { showTestSmsCode } from '@/utils/testSms'
import { useAuthStore } from '@/stores/auth'
const router = useRouter() const router = useRouter()
// 激活页语义 = 未登录。必须主动清除浏览器中可能残留的登录态:
// 否则激活成功/点「返回登录」跳 /login 时,router guard(router/index.js:203-222)
// 见到 isLoggedIn && role==='admin' 会把用户重定向进 /admin —— 公用电脑上
// 前一位管理员未退出时,下一位激活的考生会被直接送进管理后台且接口权限可用(R61)。
const authStore = useAuthStore()
// ==================== 状态 ==================== // ==================== 状态 ====================
@@ -408,6 +416,9 @@ async function handleActivate() {
smsCode: step2Form.smsCode, smsCode: step2Form.smsCode,
}) })
ElMessage.success('账号激活成功!请登录参赛') ElMessage.success('账号激活成功!请登录参赛')
// 兜底再清一次(R61):确保跳转瞬间 localStorage 内无残留登录态,
// 否则 /login 的守卫会把用户送进 /admin。
authStore.clearAuth()
// 跳转到登录页 // 跳转到登录页
setTimeout(() => { setTimeout(() => {
router.push('/login') router.push('/login')
@@ -452,6 +463,9 @@ function startSmsCountdown() {
// ==================== 生命周期 ==================== // ==================== 生命周期 ====================
onMounted(() => { onMounted(() => {
// 进入激活页即按「未登录」处理(R61):清掉残留 token/user,
// 覆盖两条会跳 /login 的路径 —— ①本页「返回登录」按钮 ②激活成功后的跳转。
authStore.clearAuth()
refreshCaptcha() refreshCaptcha()
}) })

View File

@@ -139,6 +139,7 @@
<el-input <el-input
v-model="step3Form.password" v-model="step3Form.password"
type="password" type="password"
autocomplete="new-password"
placeholder="请设置新密码(至少6位)" placeholder="请设置新密码(至少6位)"
size="large" size="large"
show-password show-password
@@ -149,6 +150,7 @@
<el-input <el-input
v-model="step3Form.confirmPassword" v-model="step3Form.confirmPassword"
type="password" type="password"
autocomplete="new-password"
placeholder="请再次输入新密码" placeholder="请再次输入新密码"
size="large" size="large"
show-password show-password

View File

@@ -54,6 +54,7 @@
<el-input <el-input
v-model="contestantForm.password" v-model="contestantForm.password"
type="password" type="password"
autocomplete="current-password"
placeholder="请输入密码" placeholder="请输入密码"
:prefix-icon="Lock" :prefix-icon="Lock"
size="large" size="large"
@@ -103,6 +104,7 @@
<el-input <el-input
v-model="adminForm.password" v-model="adminForm.password"
type="password" type="password"
autocomplete="current-password"
placeholder="请输入密码" placeholder="请输入密码"
:prefix-icon="Lock" :prefix-icon="Lock"
size="large" size="large"