前言
体验地址 weblog.lihk.top
是的,你没有看错,就是2.99元,前期需要准备一个serv00账号,cloundfare账号,阿里云域名(没有的话也可以不准备)
所使用的代码工具:cursor
前端使用vue3+ts+antd+vite,后端是使用nest+mysql
前期项目搭建使用cursor搭建,逐步搭建好
nest全局统一返回
接口统一返回的格式为code、msg、data
// 全局统一返回
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
} from '@nestjs/common';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const status = exception.getStatus();
const exceptionResponse = exception.getResponse();
response.status(status).json({
code: status,
msg: exceptionResponse['message'] || 'An error occurred',
data: null,
});
}
}
连接mysql数据库
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import * as dotenv from 'dotenv';
dotenv.config(); // 加载 .env 文件
export const databaseConfig: TypeOrmModuleOptions = {
type: 'mysql', // 数据库类型,可更改为 'postgres', 'sqlite' 等
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT, 10),
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
entities: [__dirname + '/../**/*.entity.{js,ts}'], // 实体文件路径
synchronize: true, // 是否自动同步数据库,
logging: true, // 开启日志输出
// 设置为utf8mb4字符集
charset: 'utf8mb4',
extra: {
charset: 'utf8mb4', // 这里也指定字符集
},
};
aes接口加密
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import * as crypto from 'crypto';
import * as dotenv from 'dotenv';
dotenv.config();
@Injectable()
export class ResponseInterceptor implements NestInterceptor {
private readonly secretKey;
constructor() {
this.secretKey = crypto
.createHash('sha256')
.update(process.env.CRYPTO_KEY)
.digest();
}
encryptData(data: any): string {
// 生成随机 IV
const iv = crypto.randomBytes(16); // AES-256-CBC 的 IV 长度为 16 字节
const cipher = crypto.createCipheriv('aes-256-cbc', this.secretKey, iv);
// 加密数据
let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'base64');
encrypted += cipher.final('base64');
// 返回 IV 和加密数据的组合
return iv.toString('base64') + ':' + encrypted;
}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
map((data) => {
// 如果没有设置 CRYPTO_KEY,则直接返回数据
const encryptedData = process.env.CRYPTO_KEY
? this.encryptData(data)
: data;
return { code: 200, msg: 'success', data: encryptedData };
}),
);
}
}
接口会对其的返回数据进行加密,前端进行解密即可获取正确的接口返回信息
Swagger接口文档配置
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle('NestJS Template API')
.setDescription('API documentation for the NestJS template')
.setVersion('1.0')
.addBearerAuth(
{
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
in: 'header',
name: 'Authorization',
},
'bearer',
)
.addSecurityRequirements('bearer')
.build();
const document = SwaggerModule.createDocument(app, config);
// Swagger项目中使用
@Get()
@ApiOperation({ summary: '获取文章列表' })
async getArticles(
@Query('page') page: number = 1,
@Query('pageSize') pageSize: number = 10,
@Query('categoryId') categoryId?: number, // 可选参数
) {
return this.articleService.findAll(page, pageSize, categoryId);
}
实际运行效果
身份验证
在有需要的接口前面使用,这个接口就需要前端登录之后传token才可以查询到数据
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { CanActivate, ExecutionContext } from '@nestjs/common';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private readonly jwtService: JwtService) {}
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const token = request.headers['authorization']?.split(' ')[1]; // 获取 Bearer token
if (!token) {
return false; // 没有 token,返回 false
}
try {
const decoded = this.jwtService.verify(token); // 验证 token
console.log('🚀 ~ AuthGuard ~ canActivate ~ decoded:', decoded);
request.user = decoded; // 在请求中添加用户信息
return true; // 验证成功
} catch (e) {
console.log('🚀 ~ AuthGuard ~ canActivate ~ e:', e);
return false; // 验证失败
}
}
}
// 项目中使用
import { AuthGuard } from 'src/auth/auth.guard';
@UseGuards(AuthGuard)