feat: harden auth and study workflows
- replace plaintext login and unlock requests with RSA-OAEP/AES-GCM encrypted payloads - add login challenge replay protection, production RSA key validation, and auth tests - wire compose to environment-driven dev/prod settings without committing local secrets - update setup-config smoke scripts and Postman docs for encrypted login - add visit schedule migrations/tests and update study/subject setup workflows
This commit is contained in:
@@ -74,12 +74,6 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<div class="remember-row">
|
||||
<el-checkbox id="remember" v-model="form.remember" class="remember-checkbox">
|
||||
<span class="remember-text">记住此设备</span>
|
||||
</el-checkbox>
|
||||
</div>
|
||||
|
||||
<el-button type="primary" :loading="loading" @click="onSubmit" size="large" class="login-btn">
|
||||
登 录
|
||||
</el-button>
|
||||
@@ -100,7 +94,6 @@ import { useRouter } from "vue-router";
|
||||
import { ElMessage, type FormInstance, type FormRules } from "element-plus";
|
||||
import { useAuthStore } from "../store/auth";
|
||||
import { useStudyStore } from "../store/study";
|
||||
import { getCachedCredential, setCachedCredential, clearCachedCredential } from "../utils/auth";
|
||||
import { TEXT, requiredMessage } from "../locales";
|
||||
import { consumeLogoutReason, LOGOUT_REASON_TIMEOUT } from "../session/sessionManager";
|
||||
|
||||
@@ -111,7 +104,6 @@ const formRef = ref<FormInstance>();
|
||||
const form = reactive({
|
||||
email: "",
|
||||
password: "",
|
||||
remember: false,
|
||||
});
|
||||
|
||||
const rules: FormRules<typeof form> = {
|
||||
@@ -129,12 +121,7 @@ onMounted(() => {
|
||||
if (logoutReason === LOGOUT_REASON_TIMEOUT) {
|
||||
ElMessage.warning("长时间未操作,已自动退出登录,请重新登录");
|
||||
}
|
||||
const cached = getCachedCredential();
|
||||
if (cached) {
|
||||
form.email = cached.email;
|
||||
form.password = cached.password;
|
||||
form.remember = true;
|
||||
}
|
||||
form.email = localStorage.getItem("ctms_last_login_email") || "";
|
||||
});
|
||||
|
||||
const onSubmit = async () => {
|
||||
@@ -144,11 +131,6 @@ const onSubmit = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
await auth.login(form.email, form.password);
|
||||
if (form.remember) {
|
||||
setCachedCredential(form.email, form.password);
|
||||
} else {
|
||||
clearCachedCredential();
|
||||
}
|
||||
const studyStore = useStudyStore();
|
||||
if (!studyStore.currentStudy) {
|
||||
if (auth.user?.role === "ADMIN") {
|
||||
@@ -327,22 +309,6 @@ const onSubmit = async () => {
|
||||
transition: background-color 5000s ease-in-out 0s;
|
||||
}
|
||||
|
||||
.remember-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin: -6px 0 18px;
|
||||
}
|
||||
|
||||
.remember-checkbox :deep(.el-checkbox__label) {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.remember-text {
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
|
||||
Reference in New Issue
Block a user