| | |
| | | mfaDialogMode: "enable", |
| | | mfaSetupLoading: false, |
| | | mfaSubmitting: false, |
| | | passkeyDialogVisible: false, |
| | | passkeyDialogMode: "register", |
| | | passkeySubmitting: false, |
| | | form: { |
| | | id: "", |
| | | roleName: "", |
| | |
| | | mfaEnabled: 0, |
| | | mfaEnabled$: "否", |
| | | mfaBoundTime$: "", |
| | | mfaMaskedSecret: "" |
| | | mfaMaskedSecret: "", |
| | | passkeyBound: false, |
| | | passkeyName: "", |
| | | passkeyBoundTime$: "", |
| | | passkeyLastUsedTime$: "", |
| | | passkeyTransports: "" |
| | | }, |
| | | passwordForm: { |
| | | oldPassword: "", |
| | |
| | | secret: "", |
| | | qrCode: "", |
| | | otpAuth: "" |
| | | }, |
| | | passkeyForm: { |
| | | name: "", |
| | | currentPassword: "" |
| | | }, |
| | | rules: { |
| | | username: [ |
| | |
| | | }, |
| | | trigger: "blur" |
| | | } |
| | | ] |
| | | }, |
| | | passkeyRules: { |
| | | currentPassword: [ |
| | | { required: true, message: "请输入当前密码", trigger: "blur" } |
| | | ] |
| | | } |
| | | }; |
| | |
| | | } |
| | | }); |
| | | }, |
| | | openPasskeyRegisterDialog: function () { |
| | | if (!window.WCS_WEBAUTHN || !window.WCS_WEBAUTHN.isSupported()) { |
| | | this.$message.error(this.resolvePasskeyErrorMessage({ message: window.isSecureContext ? "not-supported" : "secure-context" }, "当前环境不支持通行密钥")); |
| | | return; |
| | | } |
| | | this.passkeyDialogMode = "register"; |
| | | this.resetPasskeyDialogState(); |
| | | this.passkeyDialogVisible = true; |
| | | }, |
| | | openPasskeyRemoveDialog: function () { |
| | | this.passkeyDialogMode = "remove"; |
| | | this.resetPasskeyDialogState(); |
| | | this.passkeyDialogVisible = true; |
| | | }, |
| | | closePasskeyDialog: function () { |
| | | this.passkeyDialogVisible = false; |
| | | this.resetPasskeyDialogState(); |
| | | }, |
| | | resetPasskeyDialogState: function () { |
| | | this.passkeySubmitting = false; |
| | | this.passkeyForm = { |
| | | name: "", |
| | | currentPassword: "" |
| | | }; |
| | | if (this.$refs.passkeyForm) { |
| | | this.$refs.passkeyForm.clearValidate(); |
| | | } |
| | | }, |
| | | handlePasskeySubmit: function () { |
| | | var vm = this; |
| | | if (!vm.$refs.passkeyForm) { |
| | | return; |
| | | } |
| | | vm.$refs.passkeyForm.validate(function (valid) { |
| | | if (!valid) { |
| | | return false; |
| | | } |
| | | if (vm.passkeyDialogMode === "register") { |
| | | vm.submitPasskeyRegister(); |
| | | } else { |
| | | vm.submitPasskeyRemove(); |
| | | } |
| | | return true; |
| | | }); |
| | | }, |
| | | submitPasskeyRegister: function () { |
| | | var vm = this; |
| | | if (!window.WCS_WEBAUTHN || !window.WCS_WEBAUTHN.isSupported()) { |
| | | vm.$message.error(vm.resolvePasskeyErrorMessage({ message: window.isSecureContext ? "not-supported" : "secure-context" }, "当前环境不支持通行密钥")); |
| | | return; |
| | | } |
| | | vm.passkeySubmitting = true; |
| | | $.ajax({ |
| | | url: baseUrl + "/user/passkey/register/options/auth", |
| | | headers: { token: localStorage.getItem("token") }, |
| | | method: "POST", |
| | | success: function (res) { |
| | | if (handleForbidden(res)) { |
| | | return; |
| | | } |
| | | if (Number(res.code) !== 200) { |
| | | vm.passkeySubmitting = false; |
| | | vm.$message.error(res.msg || "通行密钥配置加载失败"); |
| | | return; |
| | | } |
| | | vm.executePasskeyRegister(res.data || {}); |
| | | }, |
| | | error: function () { |
| | | vm.passkeySubmitting = false; |
| | | vm.$message.error("通行密钥配置加载失败"); |
| | | } |
| | | }); |
| | | }, |
| | | executePasskeyRegister: function (optionsPayload) { |
| | | var vm = this; |
| | | window.WCS_WEBAUTHN.register(optionsPayload).then(function (credential) { |
| | | $.ajax({ |
| | | url: baseUrl + "/user/passkey/register/finish/auth", |
| | | headers: { token: localStorage.getItem("token") }, |
| | | data: { |
| | | ticket: optionsPayload.ticket, |
| | | currentPassword: hex_md5(vm.passkeyForm.currentPassword), |
| | | name: vm.passkeyForm.name, |
| | | credentialId: credential.credentialId, |
| | | clientDataJSON: credential.clientDataJSON, |
| | | authenticatorData: credential.authenticatorData, |
| | | publicKey: credential.publicKey, |
| | | publicKeyAlgorithm: credential.publicKeyAlgorithm, |
| | | transports: credential.transports |
| | | }, |
| | | method: "POST", |
| | | success: function (res) { |
| | | if (handleForbidden(res)) { |
| | | return; |
| | | } |
| | | if (Number(res.code) !== 200) { |
| | | vm.$message.error(res.msg || "通行密钥绑定失败"); |
| | | return; |
| | | } |
| | | vm.$message.success("通行密钥已绑定"); |
| | | vm.closePasskeyDialog(); |
| | | vm.loadDetail(); |
| | | }, |
| | | error: function () { |
| | | vm.$message.error("通行密钥绑定失败"); |
| | | }, |
| | | complete: function () { |
| | | vm.passkeySubmitting = false; |
| | | } |
| | | }); |
| | | }).catch(function (err) { |
| | | vm.passkeySubmitting = false; |
| | | vm.$message.error(vm.resolvePasskeyErrorMessage(err, "通行密钥绑定失败")); |
| | | }); |
| | | }, |
| | | submitPasskeyRemove: function () { |
| | | var vm = this; |
| | | vm.passkeySubmitting = true; |
| | | $.ajax({ |
| | | url: baseUrl + "/user/passkey/remove/auth", |
| | | headers: { token: localStorage.getItem("token") }, |
| | | data: { |
| | | currentPassword: hex_md5(vm.passkeyForm.currentPassword) |
| | | }, |
| | | method: "POST", |
| | | success: function (res) { |
| | | if (handleForbidden(res)) { |
| | | return; |
| | | } |
| | | if (Number(res.code) !== 200) { |
| | | vm.$message.error(res.msg || "通行密钥解绑失败"); |
| | | return; |
| | | } |
| | | vm.$message.success("通行密钥已解绑"); |
| | | vm.closePasskeyDialog(); |
| | | vm.loadDetail(); |
| | | }, |
| | | error: function () { |
| | | vm.$message.error("通行密钥解绑失败"); |
| | | }, |
| | | complete: function () { |
| | | vm.passkeySubmitting = false; |
| | | } |
| | | }); |
| | | }, |
| | | resolvePasskeyErrorMessage: function (err, fallback) { |
| | | var message = err && err.message ? String(err.message) : ""; |
| | | if (message === "secure-context") { |
| | | return "通行密钥仅支持在 HTTPS 或 localhost 环境下使用"; |
| | | } |
| | | if (message === "not-supported" || message === "extension-unsupported" || message === "public-key-missing") { |
| | | return "当前浏览器不支持通行密钥,请使用最新版 Chrome、Edge 或 Safari"; |
| | | } |
| | | if (err && err.name === "NotAllowedError") { |
| | | return "已取消通行密钥操作或验证超时"; |
| | | } |
| | | return fallback || "通行密钥操作失败"; |
| | | }, |
| | | copySecret: function () { |
| | | var vm = this; |
| | | var text = vm.mfaSetup.secret || ""; |