mirror of
https://github.com/certd/certd.git
synced 2026-04-24 12:27:25 +08:00
perf: 优化passkey
This commit is contained in:
@@ -278,20 +278,24 @@ async function doRegisterPasskey(deviceName: string) {
|
|||||||
// type: "public-key",
|
// type: "public-key",
|
||||||
// }));
|
// }));
|
||||||
|
|
||||||
|
console.log("passkey register options:", options, JSON.stringify(options));
|
||||||
const publicKey = {
|
const publicKey = {
|
||||||
challenge: Uint8Array.from(atob(options.challenge.replace(/-/g, "+").replace(/_/g, "/")), c => c.charCodeAt(0)),
|
challenge: Uint8Array.from(atob(options.challenge.replace(/-/g, "+").replace(/_/g, "/")), c => c.charCodeAt(0)),
|
||||||
rp: options.rp,
|
rp: options.rp,
|
||||||
pubKeyCredParams: options.pubKeyCredParams,
|
pubKeyCredParams: options.pubKeyCredParams,
|
||||||
timeout: options.timeout || 60000,
|
timeout: options.timeout || 60000,
|
||||||
attestation: options.attestation,
|
// attestation: options.attestation,
|
||||||
// excludeCredentials: excludeCredentials,
|
// excludeCredentials: excludeCredentials,
|
||||||
|
// extensions: options.extensions,
|
||||||
|
// authenticatorSelection: options.authenticatorSelection,
|
||||||
|
// hints: options.hints,
|
||||||
user: {
|
user: {
|
||||||
id: new TextEncoder().encode(options.userId + ""),
|
id: new TextEncoder().encode(options.userId + ""),
|
||||||
name: userInfo.value.username,
|
name: userInfo.value.username + "@" + deviceName,
|
||||||
displayName: deviceName,
|
displayName: deviceName,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
console.log("passkey register publicKey:", publicKey);
|
console.log("passkey register publicKey:", publicKey, JSON.stringify(publicKey));
|
||||||
const credential = await (navigator.credentials as any).create({
|
const credential = await (navigator.credentials as any).create({
|
||||||
publicKey,
|
publicKey,
|
||||||
});
|
});
|
||||||
@@ -312,6 +316,7 @@ async function doRegisterPasskey(deviceName: string) {
|
|||||||
console.log("credential", credential, response);
|
console.log("credential", credential, response);
|
||||||
|
|
||||||
const verifyRes: any = await api.verifyPasskeyRegistration(response, options.challenge, deviceName);
|
const verifyRes: any = await api.verifyPasskeyRegistration(response, options.challenge, deviceName);
|
||||||
|
console.log("verifyRes:", verifyRes, JSON.stringify(verifyRes));
|
||||||
await loadPasskeys();
|
await loadPasskeys();
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error("Passkey注册失败:", e);
|
console.error("Passkey注册失败:", e);
|
||||||
|
|||||||
@@ -219,15 +219,22 @@ const handlePasskeyLogin = async () => {
|
|||||||
});
|
});
|
||||||
const options = optionsResponse;
|
const options = optionsResponse;
|
||||||
|
|
||||||
|
console.log("passkey authentication options:", options, JSON.stringify(options));
|
||||||
const credential = await (navigator.credentials as any).get({
|
const credential = await (navigator.credentials as any).get({
|
||||||
publicKey: {
|
publicKey: {
|
||||||
challenge: Uint8Array.from(atob(options.challenge.replace(/-/g, "+").replace(/_/g, "/")), c => c.charCodeAt(0)),
|
challenge: Uint8Array.from(atob(options.challenge.replace(/-/g, "+").replace(/_/g, "/")), c => c.charCodeAt(0)),
|
||||||
rpId: options.rpId,
|
rpId: options.rpId,
|
||||||
allowCredentials: options.allowCredentials || [],
|
allowCredentials: options.allowCredentials || [],
|
||||||
timeout: options.timeout || 60000,
|
timeout: options.timeout || 60000,
|
||||||
|
// attestation: options.attestation,
|
||||||
|
// excludeCredentials: excludeCredentials,
|
||||||
|
// extensions: options.extensions,
|
||||||
|
// authenticatorSelection: options.authenticatorSelection,
|
||||||
|
// hints: options.hints,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("passkey authentication credential:", credential, JSON.stringify(credential));
|
||||||
if (!credential) {
|
if (!credential) {
|
||||||
throw new Error("Passkey认证失败");
|
throw new Error("Passkey认证失败");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div class="oauth-title">
|
<div class="oauth-title">
|
||||||
<div class="oauth-title-text">{{ computedTitle }}</div>
|
<div class="oauth-title-text">{{ computedTitle }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center items-center gap-4">
|
<div class="flex justify-center items-center gap-4 flex-wrap md:flex-nowrap">
|
||||||
<template v-for="item in oauthProviderList" :key="item.type">
|
<template v-for="item in oauthProviderList" :key="item.type">
|
||||||
<div v-if="item.addonId" class="oauth-icon-button pointer" @click="goOauthLogin(item.name)">
|
<div v-if="item.addonId" class="oauth-icon-button pointer" @click="goOauthLogin(item.name)">
|
||||||
<div><fs-icon :icon="item.icon" class="text-blue-600 text-40" /></div>
|
<div><fs-icon :icon="item.icon" class="text-blue-600 text-40" /></div>
|
||||||
|
|||||||
@@ -88,10 +88,6 @@ export default (req: any) => {
|
|||||||
host: "0.0.0.0",
|
host: "0.0.0.0",
|
||||||
port: 3008,
|
port: 3008,
|
||||||
fs: devServerFs,
|
fs: devServerFs,
|
||||||
https: {
|
|
||||||
key: fs.readFileSync("./keys/localhost+1-key.pem"),
|
|
||||||
cert: fs.readFileSync("./keys/localhost+1.pem"),
|
|
||||||
},
|
|
||||||
allowedHosts: ["localhost", "127.0.0.1", "yfy.docmirror.cn", "docmirror.top", "*", "local.dev"],
|
allowedHosts: ["localhost", "127.0.0.1", "yfy.docmirror.cn", "docmirror.top", "*", "local.dev"],
|
||||||
proxy: {
|
proxy: {
|
||||||
// with options
|
// with options
|
||||||
|
|||||||
@@ -95,9 +95,7 @@ export class LoginController extends BaseController {
|
|||||||
this.ctx
|
this.ctx
|
||||||
);
|
);
|
||||||
|
|
||||||
return this.ok({
|
return this.ok(options);
|
||||||
...options,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/loginByPasskey', { description: Constants.per.guest })
|
@Post('/loginByPasskey', { description: Constants.per.guest })
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ export class MinePasskeyController extends BaseController {
|
|||||||
|
|
||||||
return this.ok({
|
return this.ok({
|
||||||
...options,
|
...options,
|
||||||
userId
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,8 +51,6 @@ export class AutoAInitSite {
|
|||||||
//加载一次密钥
|
//加载一次密钥
|
||||||
await this.sysSettingsService.getSecret();
|
await this.sysSettingsService.getSecret();
|
||||||
|
|
||||||
//加载设置
|
|
||||||
await this.sysSettingsService.reloadSettings();
|
|
||||||
|
|
||||||
// 授权许可
|
// 授权许可
|
||||||
try {
|
try {
|
||||||
@@ -60,6 +58,9 @@ export class AutoAInitSite {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('授权许可验证失败', e);
|
logger.error('授权许可验证失败', e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//加载设置
|
||||||
|
await this.sysSettingsService.reloadSettings();
|
||||||
|
|
||||||
//加载站点隐藏配置
|
//加载站点隐藏配置
|
||||||
await this.safeService.reloadHiddenStatus(true)
|
await this.safeService.reloadHiddenStatus(true)
|
||||||
|
|||||||
@@ -60,6 +60,13 @@ export class PasskeyService extends BaseService<PasskeyEntity> {
|
|||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
attestationType: "none",
|
attestationType: "none",
|
||||||
excludeCredentials: [],
|
excludeCredentials: [],
|
||||||
|
preferredAuthenticatorType: 'localDevice',
|
||||||
|
authenticatorSelection: {
|
||||||
|
authenticatorAttachment: "cross-platform",
|
||||||
|
userVerification: "preferred",
|
||||||
|
residentKey: "preferred",
|
||||||
|
requireResidentKey: false
|
||||||
|
},
|
||||||
});
|
});
|
||||||
logger.info('[passkey] 注册选项:', JSON.stringify(options));
|
logger.info('[passkey] 注册选项:', JSON.stringify(options));
|
||||||
cache.set(`passkey:registration:${options.challenge}`, userId, {
|
cache.set(`passkey:registration:${options.challenge}`, userId, {
|
||||||
@@ -121,6 +128,7 @@ export class PasskeyService extends BaseService<PasskeyEntity> {
|
|||||||
rpID: rpId,
|
rpID: rpId,
|
||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
allowCredentials: [],
|
allowCredentials: [],
|
||||||
|
userVerification: 'preferred' //'required' | 'preferred' | 'discouraged';
|
||||||
});
|
});
|
||||||
|
|
||||||
// cache.set(`passkey:authentication:${options.challenge}`, userId, {
|
// cache.set(`passkey:authentication:${options.challenge}`, userId, {
|
||||||
|
|||||||
Reference in New Issue
Block a user