tokenservice
parent
8640838804
commit
29d886788f
|
@ -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 {
|
||||||
|
|
|
@ -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 }),
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { UserEntity } from "../entities/user.entity";
|
||||||
|
|
||||||
|
const user = UserEntity.findOne({
|
||||||
|
where: { id: "9d412d99-c725-4c9f-a555-3dd88bd607d6" },
|
||||||
|
});
|
||||||
|
console.log(user);
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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: [],
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue