import { defineStore } from "pinia"; import { ref } from "vue"; import request from "@/utils/request"; import { useRouter } from "vue-router"; import { startRegistration, startAuthentication } from "@simplewebauthn/browser"; import { useAuthStore } from "./auth"; export const useWebAuthStore = defineStore("webauth", () => { const router = useRouter(); // const token = ref(localStorage.getItem("token") || ""); const passkeys = ref(null); const loading = ref(false); const error = ref(null); const addPasskey = async () => { error.value = ""; loading.value = true; try { // 1. 从后端获取注册选项 (Creation Options) const res = await request.get("/profile/passkey"); // console.log("begin:", res.data.data.publicKey); const options = res.data.data.publicKey; // 调用 Web Authentication API 进行注册 // const credential = await navigator.credentials.create(options); // console.log("credential:", credential); let attestation; try { // Pass 'undefined' as the second argument if you are not using an AbortSignal attestation = await startRegistration({optionsJSON: options}); // console.log("WebAuthn 注册结果 (Attestation):", JSON.stringify(attestation)); error.value = null; } catch (regError) { // console.log("WebAuthn 注册失败或取消:", regError); if (regError.name === "NotAllowedError") { error.value = "Passkey 操作被取消或不允许。"; } else { error.value = `Passkey 创建出错: ${regError.message}`; } return; // 终止流程 } // 3. 将注册结果 (Attestation) 发送到后端进行验证和保存 const res2 = await request.post("/profile/passkey", attestation); // console.log("end:", res2); return res2; } catch (err) { error.value =err.response?.data?.error || "添加 Passkey 失败,请稍后重试。"; throw error } finally { loading.value = false; } }; const loginPasskey = async () => { error.value = null; loading.value = true; try { // 1. 从后端获取登录选项 (Assertion Options) const res = await request.get("/auth/passkey/begin"); // console.log("login begin:", res.data); const options = res.data.data.publicKey; // 2. 调用 Web Authentication API 进行认证 let assertion; try { assertion = await startAuthentication({ optionsJSON: options }); // console.log("WebAuthn 认证结果 (Assertion):", JSON.stringify(assertion)); } catch (loginError) { if (loginError.name === "NotAllowedError") { error.value = "Passkey 登录被取消或不允许。"; } else { error.value = `Passkey 登录出错: ${loginError.message}`; } throw error; } // 3. 将认证结果 (Assertion) 发送到后端进行验证并获取 Token const challenge = options.challenge; // 从 begin 接口返回的 options 中获取 challenge const res2 = await request.post(`/auth/passkey/finish?challenge=${challenge}`, assertion); // 4. 处理登录成功的响应,通常包含 Token if (res2.status === 200 && !!res2.data.data?.token) { const token = res2.data.data.token const authStore = useAuthStore() authStore.setToken(token) await authStore.getProfile() return res2.data } } catch (err) { error.value = err.response?.data?.error || err.value || "Passkey 登录失败,请稍后重试。"; throw error; } finally { loading.value = false; } }; const getPasskeys = async () => { loading.value = true; error.value = null; try { const response = await request.get('/profile/passkeys') // console.log('getPasskeys',response.data.data) passkeys.value = response.data.data } catch (err) { error.value = err.response?.data?.error || '获取token列表失败'; throw error }finally { loading.value = false; } } const deletePasskey = async (id) => { loading.value = true; error.value = null; try { const response = await request.delete(`/profile/passkeys/${id}`) return response } catch (err) { error.value = err.response?.data?.error || `删除passkey ${id} 失败`; throw error }finally { loading.value = false; } } return { passkeys, loading, error, addPasskey, loginPasskey, getPasskeys, deletePasskey, }; });