Skip to content

Commit 0564b2c

Browse files
committed
feat: 添加访问验证组件及API支持
1 parent fe61d5f commit 0564b2c

File tree

4 files changed

+111
-0
lines changed

4 files changed

+111
-0
lines changed

components/BaseAuth.vue

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<template>
2+
<div>
3+
<v-dialog v-model="isAuthDialogShow" persistent width="500">
4+
<v-card title="访问验证(三月之内验证一次)">
5+
<v-card-text>
6+
<p class="mb-2">请输入4位访问密码</p>
7+
<v-text-field
8+
v-model="password"
9+
label="密码"
10+
type="password"
11+
maxlength="4"
12+
hint="请输入4位数字密码"
13+
variant="outlined"
14+
:rules="[(value: string | any[]) => (value && value.length === 4) || '请输入4位密码']"
15+
></v-text-field>
16+
17+
<div class="text-center my-4">
18+
<p>可扫码获取验证码(扫码->验证码->SSGO)</p>
19+
<img src="/qrcode.jpg" alt="扫码获取验证码" class="qrcode-image" />
20+
</div>
21+
</v-card-text>
22+
23+
<v-card-actions>
24+
<v-spacer></v-spacer>
25+
<v-btn color="primary" @click="verifyPassword">验证</v-btn>
26+
</v-card-actions>
27+
</v-card>
28+
</v-dialog>
29+
</div>
30+
</template>
31+
32+
<script lang="ts" setup>
33+
import { ref, onMounted } from 'vue';
34+
35+
const isAuthDialogShow = ref(false);
36+
const password = ref('');
37+
38+
const checkAuth = async () => {
39+
// 从localStorage获取password
40+
const storedPassword = localStorage.getItem('password');
41+
42+
if (storedPassword) {
43+
try {
44+
// 请求API验证密码
45+
const response = await fetch(`/api/auth?password=${storedPassword}`);
46+
const isAuthorized = await response.json();
47+
48+
// 根据返回结果决定是否显示弹窗
49+
if (!isAuthorized) {
50+
isAuthDialogShow.value = true;
51+
}
52+
} catch (error) {
53+
console.error('验证请求失败:', error);
54+
isAuthDialogShow.value = true;
55+
}
56+
} else {
57+
// 没有存储的密码,显示弹窗
58+
isAuthDialogShow.value = true;
59+
}
60+
};
61+
62+
const verifyPassword = async () => {
63+
if (password.value.length === 4) {
64+
try {
65+
// 请求API验证输入的密码
66+
const response = await fetch(`/api/auth?password=${password.value}`);
67+
const isAuthorized = await response.json();
68+
69+
if (isAuthorized) {
70+
// 验证成功,保存密码并关闭弹窗
71+
localStorage.setItem('password', password.value);
72+
isAuthDialogShow.value = false;
73+
} else {
74+
// 验证失败,提示用户
75+
alert('密码错误,请重新输入');
76+
password.value = '';
77+
}
78+
} catch (error) {
79+
console.error('验证请求失败:', error);
80+
}
81+
}
82+
};
83+
84+
onMounted(() => {
85+
// 组件挂载5秒后执行验证
86+
setTimeout(checkAuth, 3000);
87+
});
88+
</script>
89+
90+
<style>
91+
.qrcode-image {
92+
max-width: 200px;
93+
margin: 0 auto;
94+
display: block;
95+
}
96+
</style>

pages/index.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
</template>
5252
</v-data-iterator>
5353
</v-sheet>
54+
<base-auth></base-auth>
5455
</div>
5556
</template>
5657

public/qrcode.jpg

26.5 KB
Loading

server/api/auth/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export default defineEventHandler(async (event) => {
2+
// 从请求中获取密码参数
3+
const query = getQuery(event);
4+
const providedPassword = query.password || '';
5+
6+
// 获取环境变量中的密码
7+
const weixinPassword = process.env.WEIXIN_PWD || '';
8+
9+
// 对比密码是否相同
10+
const isAuthenticated = providedPassword === weixinPassword;
11+
12+
// 返回验证结果
13+
return isAuthenticated;
14+
})

0 commit comments

Comments
 (0)