feat(安全): 增加验证码和安全验证功能

refactor(XSS): 重构XSS过滤逻辑并添加JSON反序列化过滤

feat(防重放): 前端添加防重放攻击机制

fix(验证码): 优化验证码生成和异常处理

style: 格式化代码并修复部分警告
This commit is contained in:
ikmkj
2026-03-03 18:45:08 +08:00
parent 61aeba9c65
commit 07454a28d2
11 changed files with 485 additions and 102 deletions

View File

@@ -38,6 +38,14 @@
</template>
</el-result>
</div>
<!-- 验证码弹窗 -->
<CaptchaDialog
v-model="captchaVisible"
:description="captchaDescription"
@confirm="handleCaptchaConfirm"
@cancel="handleCaptchaCancel"
/>
</template>
<script setup>
@@ -46,11 +54,18 @@ import { useRouter } from 'vue-router';
import { ElMessage, ElMessageBox } from 'element-plus';
import { getTrash, restoreTrashItem, permanentlyDeleteItem, cleanTrash } from '@/api/CommonApi.js';
import { useUserStore } from '../stores/user';
import CaptchaDialog from '@/components/CaptchaDialog.vue';
const router = useRouter();
const userStore = useUserStore();
const trashItems = ref([]);
// 验证码相关
const captchaVisible = ref(false);
const captchaDescription = ref('');
const pendingAction = ref(null);
const pendingItem = ref(null);
const fetchTrashItems = async () => {
try {
const response = await getTrash();
@@ -76,13 +91,11 @@ const handleDeletePermanently = async (item) => {
cancelButtonText: '取消',
type: 'warning',
});
try {
await permanentlyDeleteItem(item.id, item.type);
ElMessage.success('已永久删除');
fetchTrashItems();
} catch (error) {
ElMessage.error('删除失败');
}
// 保存操作和项目,显示验证码弹窗
pendingAction.value = 'delete';
pendingItem.value = item;
captchaDescription.value = '永久删除需要安全验证';
captchaVisible.value = true;
};
const handleCleanTrash = async () => {
@@ -91,15 +104,38 @@ const handleCleanTrash = async () => {
cancelButtonText: '取消',
type: 'warning',
});
// 保存操作,显示验证码弹窗
pendingAction.value = 'clean';
pendingItem.value = null;
captchaDescription.value = '清空回收站需要安全验证';
captchaVisible.value = true;
};
// 验证码确认
const handleCaptchaConfirm = async ({ captchaId, captchaCode }) => {
try {
await cleanTrash();
ElMessage.success('回收站已清空');
if (pendingAction.value === 'delete' && pendingItem.value) {
await permanentlyDeleteItem(pendingItem.value.id, pendingItem.value.type, captchaId, captchaCode);
ElMessage.success('已永久删除');
} else if (pendingAction.value === 'clean') {
await cleanTrash(captchaId, captchaCode);
ElMessage.success('回收站已清空');
}
captchaVisible.value = false;
pendingAction.value = null;
pendingItem.value = null;
fetchTrashItems();
} catch (error) {
ElMessage.error('清空失败');
ElMessage.error('操作失败: ' + (error.response?.data?.msg || error.message));
}
};
// 验证码取消
const handleCaptchaCancel = () => {
pendingAction.value = null;
pendingItem.value = null;
};
const goToLogin = () => {
router.push('/login');
};
@@ -128,4 +164,4 @@ onMounted(() => {
align-items: center;
height: 100vh;
}
</style>
</style>