mirror of
https://github.com/certd/certd.git
synced 2026-04-23 19:57:27 +08:00
chore: passkey登录优化
This commit is contained in:
@@ -4,6 +4,7 @@ import { AddonService, BaseController, Constants, SysPublicSettings, SysSettings
|
||||
import { CodeService } from "../../../modules/basic/service/code-service.js";
|
||||
import { checkComm } from "@certd/plus-core";
|
||||
import { CaptchaService } from "../../../modules/basic/service/captcha-service.js";
|
||||
import { PasskeyService } from "../../../modules/login/service/passkey-service.js";
|
||||
|
||||
/**
|
||||
*/
|
||||
@@ -23,6 +24,10 @@ export class LoginController extends BaseController {
|
||||
@Inject()
|
||||
captchaService: CaptchaService;
|
||||
|
||||
@Inject()
|
||||
passkeyService: PasskeyService;
|
||||
|
||||
|
||||
@Post('/login', { summary: Constants.per.guest })
|
||||
public async login(
|
||||
@Body(ALL)
|
||||
@@ -81,22 +86,36 @@ export class LoginController extends BaseController {
|
||||
return this.ok(token);
|
||||
}
|
||||
|
||||
@Post('/loginByPasskey', { summary: Constants.per.guest })
|
||||
public async loginByPasskey(
|
||||
@Body(ALL)
|
||||
body: any
|
||||
) {
|
||||
const credential = body.credential;
|
||||
const challenge = body.challenge;
|
||||
|
||||
|
||||
|
||||
const token = await this.loginService.loginByPasskey({
|
||||
credential,
|
||||
challenge,
|
||||
}, this.ctx);
|
||||
|
||||
// this.writeTokenCookie(token);
|
||||
return this.ok(token);
|
||||
}
|
||||
@Post('/passkey/generateAuthentication', { summary: Constants.per.guest })
|
||||
public async generateAuthentication() {
|
||||
const options = await this.passkeyService.generateAuthenticationOptions(
|
||||
this.ctx
|
||||
);
|
||||
|
||||
return this.ok({
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
@Post('/loginByPasskey', { summary: Constants.per.guest })
|
||||
public async loginByPasskey(
|
||||
@Body(ALL)
|
||||
body: any
|
||||
) {
|
||||
const credential = body.credential;
|
||||
const challenge = body.challenge;
|
||||
|
||||
const token = await this.loginService.loginByPasskey({
|
||||
credential,
|
||||
challenge,
|
||||
}, this.ctx);
|
||||
|
||||
// this.writeTokenCookie(token);
|
||||
return this.ok(token);
|
||||
}
|
||||
|
||||
@Post('/logout', { summary: Constants.per.authOnly })
|
||||
public logout() {
|
||||
|
||||
@@ -50,30 +50,4 @@ export class MineController extends BaseController {
|
||||
});
|
||||
return this.ok({});
|
||||
}
|
||||
|
||||
@Post('/passkeys', { summary: Constants.per.authOnly })
|
||||
public async getPasskeys() {
|
||||
const userId = this.getUserId();
|
||||
const passkeys = await this.passkeyService.find({
|
||||
select: ['id', 'deviceName', 'registeredAt'],
|
||||
where: { userId }});
|
||||
return this.ok(passkeys);
|
||||
}
|
||||
|
||||
@Post('/unbindPasskey', { summary: Constants.per.authOnly })
|
||||
public async unbindPasskey(@Body(ALL) body: any) {
|
||||
const userId = this.getUserId();
|
||||
const passkeyId = body.id;
|
||||
|
||||
const passkey = await this.passkeyService.findOne({
|
||||
where: { id: passkeyId, userId },
|
||||
});
|
||||
|
||||
if (!passkey) {
|
||||
throw new Error('Passkey不存在');
|
||||
}
|
||||
|
||||
await this.passkeyService.delete([passkey.id]);
|
||||
return this.ok({});
|
||||
}
|
||||
}
|
||||
|
||||
+37
-21
@@ -4,8 +4,8 @@ import { BaseController, Constants } from "@certd/lib-server";
|
||||
import { UserService } from "../../../modules/sys/authority/service/user-service.js";
|
||||
|
||||
@Provide()
|
||||
@Controller('/api/passkey')
|
||||
export class PasskeyController extends BaseController {
|
||||
@Controller('/api/mine/passkey')
|
||||
export class MinePasskeyController extends BaseController {
|
||||
@Inject()
|
||||
passkeyService: PasskeyService;
|
||||
|
||||
@@ -39,12 +39,12 @@ export class PasskeyController extends BaseController {
|
||||
});
|
||||
}
|
||||
|
||||
@Post('/verifyRegistration', { summary: Constants.per.guest })
|
||||
@Post('/verifyRegistration', { summary: Constants.per.authOnly })
|
||||
public async verifyRegistration(
|
||||
@Body(ALL)
|
||||
body: any
|
||||
) {
|
||||
const userId = body.userId;
|
||||
const userId = this.getUserId()
|
||||
const response = body.response;
|
||||
const challenge = body.challenge;
|
||||
const deviceName = body.deviceName;
|
||||
@@ -60,28 +60,14 @@ export class PasskeyController extends BaseController {
|
||||
return this.ok(result);
|
||||
}
|
||||
|
||||
@Post('/generateAuthentication', { summary: Constants.per.guest })
|
||||
public async generateAuthentication(
|
||||
@Body(ALL)
|
||||
body: any
|
||||
) {
|
||||
const options = await this.passkeyService.generateAuthenticationOptions(
|
||||
this.ctx
|
||||
);
|
||||
|
||||
|
||||
return this.ok({
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Post('/register', { summary: Constants.per.guest })
|
||||
@Post('/register', { summary: Constants.per.authOnly })
|
||||
public async registerPasskey(
|
||||
@Body(ALL)
|
||||
body: any
|
||||
) {
|
||||
const userId = body.userId;
|
||||
const userId = this.getUserId();
|
||||
const response = body.response;
|
||||
const deviceName = body.deviceName;
|
||||
const challenge = body.challenge;
|
||||
@@ -96,4 +82,34 @@ export class PasskeyController extends BaseController {
|
||||
|
||||
return this.ok(result);
|
||||
}
|
||||
|
||||
|
||||
@Post('/list', { summary: Constants.per.authOnly })
|
||||
public async getPasskeys() {
|
||||
const userId = this.getUserId();
|
||||
const passkeys = await this.passkeyService.find({
|
||||
select: ['id', 'deviceName', 'registeredAt', 'transports', 'passkeyId' ,'updateTime'],
|
||||
where: { userId },
|
||||
order: { registeredAt: 'DESC' },
|
||||
});
|
||||
return this.ok(passkeys);
|
||||
}
|
||||
|
||||
@Post('/unbind', { summary: Constants.per.authOnly })
|
||||
public async unbindPasskey(@Body(ALL) body: any) {
|
||||
const userId = this.getUserId();
|
||||
const passkeyId = body.id;
|
||||
|
||||
const passkey = await this.passkeyService.findOne({
|
||||
where: { id: passkeyId, userId },
|
||||
});
|
||||
|
||||
if (!passkey) {
|
||||
throw new Error('Passkey不存在');
|
||||
}
|
||||
|
||||
await this.passkeyService.delete([passkey.id]);
|
||||
return this.ok({});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import { cache } from "@certd/basic";
|
||||
import { AuthException, BaseService } from "@certd/lib-server";
|
||||
import { AuthException, BaseService, SysSettingsService, SysSiteInfo } from "@certd/lib-server";
|
||||
import { isComm } from "@certd/plus-core";
|
||||
import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
|
||||
import { InjectEntityModel } from "@midwayjs/typeorm";
|
||||
import { Repository } from "typeorm";
|
||||
import { UserService } from "../../sys/authority/service/user-service.js";
|
||||
import { PasskeyEntity } from "../entity/passkey.js";
|
||||
import { Repository } from "typeorm";
|
||||
import { InjectEntityModel } from "@midwayjs/typeorm";
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
@@ -16,15 +17,31 @@ export class PasskeyService extends BaseService<PasskeyEntity> {
|
||||
@InjectEntityModel(PasskeyEntity)
|
||||
repository: Repository<PasskeyEntity>;
|
||||
|
||||
@Inject()
|
||||
sysSettingsService: SysSettingsService;
|
||||
|
||||
getRepository(): Repository<PasskeyEntity> {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async getRpInfo(){
|
||||
let rpName = "Certd"
|
||||
if(isComm()){
|
||||
const siteInfo = await this.sysSettingsService.getSetting<SysSiteInfo>(SysSiteInfo);
|
||||
rpName = siteInfo.title || rpName;
|
||||
}
|
||||
return {
|
||||
rpName,
|
||||
}
|
||||
}
|
||||
async generateRegistrationOptions(userId: number, username: string, remoteIp: string, ctx: any) {
|
||||
const { generateRegistrationOptions } = await import("@simplewebauthn/server");
|
||||
const user = await this.userService.info(userId);
|
||||
|
||||
const {rpName} = await this.getRpInfo();
|
||||
|
||||
const options = await generateRegistrationOptions({
|
||||
rpName: "Certd",
|
||||
rpName: rpName,
|
||||
rpID: this.getRpId(ctx),
|
||||
userID: new Uint8Array([userId]),
|
||||
userName: username,
|
||||
@@ -184,6 +201,7 @@ export class PasskeyService extends BaseService<PasskeyEntity> {
|
||||
}
|
||||
|
||||
passkey.counter = verification.counter;
|
||||
passkey.updateTime = new Date();
|
||||
await this.repository.save(passkey);
|
||||
|
||||
const user = await this.userService.info(passkey.userId);
|
||||
|
||||
Reference in New Issue
Block a user