tokenservice

master
lee 2025-05-23 16:31:58 +08:00
parent 8640838804
commit 29d886788f
8 changed files with 80 additions and 39 deletions

View File

@ -1,9 +1,8 @@
import { Global, Logger, Module, ValidationPipe } from "@nestjs/common"; import { Global, Logger, Module, ValidationPipe } from "@nestjs/common";
import { APP_FILTER, APP_PIPE } from "@nestjs/core"; import { APP_PIPE } from "@nestjs/core";
import { ConfigModule } from "./common/config/config.module"; import { ConfigModule } from "./common/config/config.module";
import { database } from "./config/database.config"; import { database } from "./config/database.config";
import { AppFilter } from "./filters/app.filter";
import { Env } from "./modules/config/env"; import { Env } from "./modules/config/env";
import { DatabaseModule } from "./modules/database/database.module"; import { DatabaseModule } from "./modules/database/database.module";
import { UserModule } from "./modules/user/user.module"; import { UserModule } from "./modules/user/user.module";
@ -31,10 +30,10 @@ import { UserModule } from "./modules/user/user.module";
provide: APP_PIPE, provide: APP_PIPE,
useClass: ValidationPipe, useClass: ValidationPipe,
}, },
{ // {
provide: APP_FILTER, // provide: APP_FILTER,
useClass: AppFilter, // useClass: AppFilter,
}, // },
], ],
}) })
export class AppModule { export class AppModule {

View File

@ -4,12 +4,8 @@ import { useContainer } from "class-validator";
import { WinstonModule } from "nest-winston"; import { WinstonModule } from "nest-winston";
import { AppModule } from "./app.module"; import { AppModule } from "./app.module";
import { findup } from "./modules/config/findup";
import { instance } from "./until/winstonconfig"; import { instance } from "./until/winstonconfig";
const envFile = findup(".env");
console.log(envFile);
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule, { const app = await NestFactory.create(AppModule, {
logger: WinstonModule.createLogger({ instance }), logger: WinstonModule.createLogger({ instance }),

View File

@ -1,12 +1,11 @@
import type { DynamicModule, ModuleMetadata } from "@nestjs/common"; import type { DynamicModule, ModuleMetadata } from "@nestjs/common";
import type { TypeOrmModuleOptions } from "@nestjs/typeorm"; import type { TypeOrmModuleOptions } from "@nestjs/typeorm";
import { Global, Module } from "@nestjs/common"; import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm"; import { TypeOrmModule } from "@nestjs/typeorm";
import { UniqueConstraint } from "../user/constraints/unique.constraint"; import { UniqueConstraint } from "../user/constraints/unique.constraint";
@Global()
@Module({}) @Module({})
export class DatabaseModule { export class DatabaseModule {
static forRoot(config: TypeOrmModuleOptions): DynamicModule { static forRoot(config: TypeOrmModuleOptions): DynamicModule {

View File

@ -1,19 +1,26 @@
import { Body, Controller, Get, Post, SerializeOptions } from "@nestjs/common"; import { Body, Controller, Get, Post, SerializeOptions } from "@nestjs/common";
import { CreateUserDto } from "../dtos/user.dto";
import { UserEntity } from "../entities/user.entity"; import { UserEntity } from "../entities/user.entity";
import { TokenService } from "../services/token.service";
import { UserService } from "../services/user.service"; import { UserService } from "../services/user.service";
@Controller("users") @Controller("users")
export class UserController { export class UserController {
constructor(private readonly service: UserService) {} constructor(
private readonly service: UserService,
private tokenService: TokenService,
) {}
@Get("/") @Get("/")
async index() { async index() {
return UserEntity.find(); const user = (await UserEntity.findOne({
where: { id: "9d412d99-c725-4c9f-a555-3dd88bd607d6" },
})) as UserEntity;
const now = Number(new Date());
return this.tokenService.generateToken(user, now);
} }
@Post("/") @Post("/")
@SerializeOptions({}) @SerializeOptions({})
async create(@Body() data: CreateUserDto) { async create(@Body() data: any) {
return this.service.create(data); return this.tokenService.verifyAccessToken(data.token);
} }
} }

View File

@ -0,0 +1,6 @@
import { UserEntity } from "../entities/user.entity";
const user = UserEntity.findOne({
where: { id: "9d412d99-c725-4c9f-a555-3dd88bd607d6" },
});
console.log(user);

View File

@ -1,6 +1,8 @@
import { Injectable } from "@nestjs/common"; import { Injectable } from "@nestjs/common";
import { JwtService } from "@nestjs/jwt"; import { JwtService } from "@nestjs/jwt";
import dayjs from "dayjs"; import { InjectRepository } from "@nestjs/typeorm";
import { Response } from "express";
import { Repository } from "typeorm";
import { v7 } from "uuid"; import { v7 } from "uuid";
import { AccessTokenEntity } from "../entities/access-token.entity"; import { AccessTokenEntity } from "../entities/access-token.entity";
@ -11,32 +13,52 @@ import { JwtConfig, JwtPayload } from "../types";
@Injectable() @Injectable()
export class TokenService { export class TokenService {
private config: JwtConfig = { private config: JwtConfig = {
token_expired: 60, token_expired: 60 * 60,
refresh_token_expired: 60 * 24 * 7, refresh_token_expired: 60 * 60 * 24 * 7,
}; };
private access_secret = "hTVLuGqhuKZW9HUnKzs83yvVBitlwc5d0PNfJqDRsRs="; private access_secret = "hTVLuGqhuKZW9HUnKzs83yvVBitlwc5d0PNfJqDRsRs=";
constructor(protected jwtService: JwtService) {}
constructor(
protected jwtService: JwtService,
@InjectRepository(AccessTokenEntity)
protected accesTokenRepository: Repository<AccessTokenEntity>,
@InjectRepository(RefreshTokenEntity)
protected refreshaccesTokenRepository: Repository<RefreshTokenEntity>,
) {}
async refreshToken(accesToken: AccessTokenEntity, response: Response) {
const { user, refreshToken } = accesToken;
if (refreshToken) {
const now = Number(new Date());
if (now < Number(refreshToken.expired_at)) return null;
const token = await this.generateToken(user, now);
await accesToken.remove();
response.header("token", token.accessToken.value);
return token;
}
return null;
}
// Generate access token // Generate access token
async generateToken(user: UserEntity, now: dayjs.Dayjs) { // 生成accesstoken的时候生成refresh token
async generateToken(user: UserEntity, now: number) {
const accessTokenPayload: JwtPayload = { const accessTokenPayload: JwtPayload = {
sub: user.id, sub: user.id,
iat: now.unix(), iat: now,
}; };
const signed = this.jwtService.sign(accessTokenPayload); const signed = this.jwtService.sign(accessTokenPayload, {
secret: this.access_secret,
});
const accessToken = new AccessTokenEntity(); const accessToken = new AccessTokenEntity();
accessToken.value = signed; accessToken.value = signed;
accessToken.user = user; accessToken.user = user;
accessToken.expired_at = now accessToken.expired_at = new Date(now + this.config.token_expired * 1000);
.add(this.config.token_expired, "second") await this.accesTokenRepository.save(accessToken);
.toDate();
await accessToken.save();
const refreshToken = await this.generateRefreshToken(accessToken, now); const refreshToken = await this.generateRefreshToken(accessToken, now);
return { accessToken, refreshToken }; return { accessToken, refreshToken };
} }
async generateRefreshToken(accessToken: AccessTokenEntity, now: dayjs.Dayjs) { async generateRefreshToken(accessToken: AccessTokenEntity, now: number) {
const refreshTokenPayload = { const refreshTokenPayload = {
uuid: v7(), uuid: v7(),
}; };
@ -45,17 +67,14 @@ export class TokenService {
secret: this.access_secret, secret: this.access_secret,
}); });
refreshToken.accessToken = accessToken; refreshToken.accessToken = accessToken;
refreshToken.expired_at = now refreshToken.expired_at = new Date(
.add(this.config.refresh_token_expired, "second") now + this.config.refresh_token_expired * 1000,
.toDate(); );
await refreshToken.save(); await refreshToken.save();
return refreshToken; return refreshToken;
} }
async checkAccessToken(token: string) { async checkAccessToken(token: string) {
return AccessTokenEntity.findOne({ return this.accesTokenRepository.findOne({ where: { value: token } });
where: { value: token },
relations: ["user", "refreshToken"],
});
} }
async rmAccessToken(token: string) { async rmAccessToken(token: string) {
const accessToken = await AccessTokenEntity.findOne({ const accessToken = await AccessTokenEntity.findOne({
@ -64,7 +83,9 @@ export class TokenService {
accessToken && (await accessToken.remove()); accessToken && (await accessToken.remove());
} }
async verifyAccessToken(token: string) { async verifyAccessToken(token: string) {
const user = await this.jwtService.verify(token, {}); const user = await this.jwtService.verify(token, {
secret: this.access_secret,
});
return user || false; return user || false;
} }
} }

View File

@ -1,15 +1,28 @@
import { Module } from "@nestjs/common"; import { Module } from "@nestjs/common";
import { JwtModule, JwtService } from "@nestjs/jwt";
import { TypeOrmModule } from "@nestjs/typeorm"; import { TypeOrmModule } from "@nestjs/typeorm";
import { UniqueConstraint } from "./constraints/unique.constraint"; import { UniqueConstraint } from "./constraints/unique.constraint";
import { UserController } from "./controller/user.controller"; import { UserController } from "./controller/user.controller";
import { UserEntity } from "./entities/user.entity"; import { UserEntity } from "./entities/user.entity";
import { TokenService } from "./services/token.service";
import { UserService } from "./services/user.service"; import { UserService } from "./services/user.service";
import { UserSubscriber } from "./subscribers/user.subscriber"; import { UserSubscriber } from "./subscribers/user.subscriber";
@Module({ @Module({
imports: [TypeOrmModule.forFeature([UserEntity])], imports: [
providers: [UserSubscriber, UserService, UniqueConstraint], TypeOrmModule.forFeature([UserEntity]),
JwtModule.register({
secret: "hTVLuGqhuKZW9HUnKzs83yvVBitlwc5d0PNfJqDRsRs=",
}),
],
providers: [
UserSubscriber,
UserService,
UniqueConstraint,
TokenService,
JwtService,
],
controllers: [UserController], controllers: [UserController],
exports: [], exports: [],
}) })

View File