[{"data":1,"prerenderedAt":322},["ShallowReactive",2],{"content:\u002Fposts\u002F2022\u002Fnestjs-setup":3,"surround:\u002Fposts\u002F2022\u002Fnestjs-setup":311},{"id":4,"title":5,"body":6,"canonical":283,"categories":284,"date":286,"description":287,"draft":288,"extension":289,"image":290,"meta":291,"navigation":296,"path":297,"permalink":283,"readingTime":298,"recommend":283,"references":283,"seo":303,"sitemap":304,"stem":305,"tags":306,"type":283,"updated":286,"__hash__":310},"content\u002Fposts\u002F2022\u002Fnestjs-setup.md","nestjs入门",{"type":7,"value":8,"toc":261},"minimark",[9,13,17,28,31,37,41,46,52,58,62,68,74,77,83,86,92,95,98,104,107,113,119,124,127,135,138,144,152,159,163,166,172,178,181,187,194,201,208,215,222,226,231,234,240,243,249,255],[10,11,12],"p",{},"nestjs 开发手册",[14,15,16],"h2",{"id":16},"安装",[18,19,25],"pre",{"className":20,"code":22,"language":23,"meta":24},[21],"language-bash","npm i -g @nestjs\u002Fcli\n","bash","",[26,27,22],"code",{"__ignoreMap":24},[14,29,30],{"id":30},"创建项目",[18,32,35],{"className":33,"code":34,"language":23,"meta":24},[21],"nest new \u003Cproject-name>\n",[26,36,34],{"__ignoreMap":24},[14,38,40],{"id":39},"nestjs-开发依赖","nestjs 开发依赖",[42,43,45],"h3",{"id":44},"orm-prisma","orm - prisma",[18,47,50],{"className":48,"code":49,"language":23,"meta":24},[21],"pnpm add prisma-binding @prisma\u002Fclient\n",[26,51,49],{"__ignoreMap":24},[18,53,56],{"className":54,"code":55,"language":23,"meta":24},[21],"pnpm add -D prisma\n",[26,57,55],{"__ignoreMap":24},[42,59,61],{"id":60},"mock-数据","mock 数据",[18,63,66],{"className":64,"code":65,"language":23,"meta":24},[21],"pnpm add mockjs\n",[26,67,65],{"__ignoreMap":24},[18,69,72],{"className":70,"code":71,"language":23,"meta":24},[21],"pnpm add -D @types\u002Fmockjs\n",[26,73,71],{"__ignoreMap":24},[42,75,76],{"id":76},"配置文件",[18,78,81],{"className":79,"code":80,"language":23,"meta":24},[21],"pnpm add @nestjs\u002Fconfig\n",[26,82,80],{"__ignoreMap":24},[42,84,85],{"id":85},"校验",[18,87,90],{"className":88,"code":89,"language":23,"meta":24},[21],"pnpm add class-validator class-transformer\n",[26,91,89],{"__ignoreMap":24},[42,93,94],{"id":94},"密码加密",[10,96,97],{},"bcrypt 依赖 python 环境",[18,99,102],{"className":100,"code":101,"language":23,"meta":24},[21],"pnpm add bcrypt\n",[26,103,101],{"__ignoreMap":24},[10,105,106],{},"或者下载 bcryptjs",[18,108,111],{"className":109,"code":110,"language":23,"meta":24},[21],"pnpm add bcryptjs\n",[26,112,110],{"__ignoreMap":24},[18,114,117],{"className":115,"code":116,"language":23,"meta":24},[21],"pnpm add -D @types\u002Fbcryptjs\n",[26,118,116],{"__ignoreMap":24},[120,121,123],"h4",{"id":122},"bcrypt-使用","bcrypt 使用",[10,125,126],{},"使用 bcrypt 加密密码",[18,128,133],{"className":129,"code":131,"language":132,"meta":24},[130],"language-ts","import { hashSync } from \"bcryptjs\"\n\u002F\u002F hasnSync(要散列的值，加密等级)\n\u002F\u002F val ? hashSync(val) : val;\n\n\u002F\u002F 对比密码是否一致\n","ts",[26,134,131],{"__ignoreMap":24},[42,136,137],{"id":137},"jwt",[18,139,142],{"className":140,"code":141,"language":23,"meta":24},[21],"pnpm add @nestjs\u002Fjwt\n",[26,143,141],{"__ignoreMap":24},[18,145,150],{"className":146,"code":148,"language":149,"meta":24},[147],"language-dotenv","SECRET = 22222\n","dotenv",[26,151,148],{"__ignoreMap":24},[18,153,157],{"className":154,"code":155,"language":132,"meta":156},[130],"import { JwtModule } from '@nestjs\u002Fjwt'\n\n@Global()\n@Module({\n    imports: [JwtModule.registerAsync({\n        useFactory() {\n            return {\n                secret: process.env.SECRET,\n            }\n        }\n    })],\n    providers: [],\n    exports: [JwtModule]\n})\nexport class JwtModule {}\n","jwt.module.ts",[26,158,155],{"__ignoreMap":24},[42,160,162],{"id":161},"passport-验证","passport 验证",[120,164,165],{"id":165},"安装依赖",[18,167,170],{"className":168,"code":169,"language":23,"meta":24},[21],"pnpm add @nestjs\u002Fpassport passport passport-local passport-jwt\n",[26,171,169],{"__ignoreMap":24},[18,173,176],{"className":174,"code":175,"language":23,"meta":24},[21],"pnpm add -D @types\u002Fpassport @types\u002Fpassport-local @types\u002Fpassport-jwt\n",[26,177,175],{"__ignoreMap":24},[120,179,180],{"id":180},"使用",[182,183,184],"blockquote",{},[10,185,186],{},"进行登录时的校验并颁发 token",[18,188,192],{"className":189,"code":190,"language":132,"meta":191},[130],"import { PassportStrategy } from \"@nestjs\u002Fpassport\"\nimport { compareSync } from \"bcryptjs\"\nimport { IStrategyOptions, Strategy } from \"passport-local\"\n\nexport class LocalStrategy extends PassportStrategy(Strategy, \"local\") {\n    \u002F\u002F local为策略的名称，默认为passport-local ,-后面的local。可以自定义名称，自定义名称后，使用AuthGuard需要指定对应的名称\n    constructor(@InjectModel(User) private userModel: ReturnModelType\u003Ctypeof User>) {\n        super({\n            usernameField: \"username\",\n            passwordField: \"password\",\n        } as IStrategyOptions)\n    }\n\n    \u002F\u002F 策略执行\n    async validate(username: string, password: string) {\n        const user = await this.userModel.findOne({ username }).select(\"password\")\n\n        \u002F\u002F 用户不存在\n        if (!user) {\n            throw new BadRequestException(\"用户名不正确\")\n        }\n        \u002F\u002F 密码不存在\n        if (!compareSync(password, user.password)) {\n            throw new BadRequestException(\"密码错误\")\n        }\n\n        return user\n    }\n}\n","local.strategy.ts",[26,193,190],{"__ignoreMap":24},[18,195,199],{"className":196,"code":197,"language":132,"meta":198},[130],"import { PassportStrategy } from \"@nestjs\u002Fpassport\"\nimport { compareSync } from \"bcryptjs\"\nimport { ExtractJwt, Strategy, StrategyOptions } from \"passport-jwt\"\n\nexport class LocalStrategy extends PassportStrategy(Strategy, \"jwt\") {\n    \u002F\u002F jwt为策略的名称，默认为passport-jwt ,-后面的jwt。可以自定义名称，自定义名称后，使用AuthGuard需要指定对应的名称\n    constructor(@InjectModel(User) private userModel: ReturnModelType\u003Ctypeof User>) {\n        super({\n            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),\n            secretOrKey: process.env.SECRET,\n        } as StrategyOptions)\n    }\n\n    \u002F\u002F 策略执行\n    async validate(id) {\n        return await this.userModel.findById(id)\n    }\n}\n","jwt.strategy.ts",[26,200,197],{"__ignoreMap":24},[18,202,206],{"className":203,"code":204,"language":132,"meta":205},[130],"export class LoginDto {\n    username: string\n    password: string\n}\n","login.dto.ts",[26,207,204],{"__ignoreMap":24},[18,209,213],{"className":210,"code":211,"language":132,"meta":212},[130],"import { Module } from \"@nestjs\u002Fcommon\"\nimport { PassportModule } from \"@nestjs\u002Fpassport\"\n\nimport { AuthController } from \".\u002Fauth.controller\"\nimport { JwtStrategy } from \".\u002Fjwt.strategy\"\nimport { LocalStrategy } from \".\u002Flocal.strategy\"\n\n@Module({\n    imports: [PassportModule],\n    controllers: [AuthController],\n    providers: [LocalStrategy, JwtStrategy],\n})\nexport class AuthModule {}\n","auth.module.ts",[26,214,211],{"__ignoreMap":24},[18,216,220],{"className":217,"code":218,"language":132,"meta":219},[130],"import { Post, UseGuards } from \"@nestjs\u002Fcommon\"\nimport { AuthGuard } from \"@nestjs\u002Fpassport\"\n\nimport { LoginDto } from \".\u002Flogin.dto.ts\"\n\nimport { JwtService } from \"\u002Fjwt.module\"\n\nexport class AuthController {\n    constructor(private jwtService: JwtService) {}\n    @Post(\"login\")\n    @UseGuards(AuthGuard(\"local\"))\n    async login(@Body() dto: LoginDto, @Req() req) {\n        return {\n            token: this.jwtService.sign(String(req.user._id)),\n        }\n    }\n\n    @Post(\"user\")\n    @UseGuards(AuthGuard(\"jwt\"))\n    async user(@Req() req) {\n        return req.user\n    }\n}\n","auth.controller.ts",[26,221,218],{"__ignoreMap":24},[42,223,225],{"id":224},"token-颁发","token 颁发",[18,227,229],{"className":228,"code":24,"language":23,"meta":24},[21],[26,230,24],{"__ignoreMap":24},[10,232,233],{},"日期处理",[18,235,238],{"className":236,"code":237,"language":23,"meta":24},[21],"pnpm add dayjs\n",[26,239,237],{"__ignoreMap":24},[10,241,242],{},"swagger 集成",[18,244,247],{"className":245,"code":246,"language":23,"meta":24},[21],"pnpm add\n",[26,248,246],{"__ignoreMap":24},[18,250,253],{"className":251,"code":252,"language":23,"meta":24},[21],"pnpm add prisma-binding @prisma\u002Fclient mockjs @nestjs\u002Fconfig class-validator class-transformer argon2 @nestjs\u002Fpassport passport passport-local @nestjs\u002Fjwt passport-jwt lodash multer dayjs express redis @nestjs\u002Fthrottler\n",[26,254,252],{"__ignoreMap":24},[18,256,259],{"className":257,"code":258,"language":23,"meta":24},[21],"pnpm add -D prisma typescript @types\u002Fnode @types\u002Fmockjs @nestjs\u002Fmapped-types @types\u002Fpassport-local @types\u002Fpassport-jwt @types\u002Fexpress @types\u002Flodash @types\u002Fmulter @types\u002Fnode\n",[26,260,258],{"__ignoreMap":24},{"title":24,"searchDepth":262,"depth":262,"links":263},4,[264,266,267],{"id":16,"depth":265,"text":16},2,{"id":30,"depth":265,"text":30},{"id":39,"depth":265,"text":40,"children":268},[269,271,272,273,274,277,278,282],{"id":44,"depth":270,"text":45},3,{"id":60,"depth":270,"text":61},{"id":76,"depth":270,"text":76},{"id":85,"depth":270,"text":85},{"id":94,"depth":270,"text":94,"children":275},[276],{"id":122,"depth":262,"text":123},{"id":137,"depth":270,"text":137},{"id":161,"depth":270,"text":162,"children":279},[280,281],{"id":165,"depth":262,"text":165},{"id":180,"depth":262,"text":180},{"id":224,"depth":270,"text":225},null,[285],"代码","2022-12-12 15:23:45","常用模块安装和使用",false,"md","https:\u002F\u002Fbitmc.uno\u002Fpicgo\u002F67a2262cef57d-78.webp",{"excerpt":292},{"type":7,"value":293},[294],[10,295,12],{},true,"\u002Fposts\u002F2022\u002Fnestjs-setup",{"text":299,"minutes":300,"time":301,"words":302},"3 min read",2.82,169200,564,{"title":5,"description":287},{"loc":297},"posts\u002F2022\u002Fnestjs-setup",[307,308,309],"nest","node","服务端","p6kWIqsUxHkRzCpzmW5EI95GBf_NGWfZCOs6aQvugkE",[312,317],{"title":313,"path":314,"stem":315,"date":316,"type":283,"children":-1},"视频网站封面图制作","\u002Fposts\u002F2022\u002Fchannel-cover","posts\u002F2022\u002Fchannel-cover","2022-12-08 22:15:26",{"title":318,"path":319,"stem":320,"date":321,"type":283,"children":-1},"申请https证书并部署至nginx服务器","\u002Fposts\u002F2022\u002Fsite-add-https","posts\u002F2022\u002Fsite-add-https","2022-12-15 15:01:33",1789642595650]