文章詳情頁
nestjs實現(xiàn)圖形校驗和單點登錄的示例代碼
瀏覽:32日期:2022-06-09 18:32:05
目錄
- 實現(xiàn)圖形校驗和單點登錄
- 前置條件
- 安裝
- Module
- service
- 如何生成圖形驗證碼
- 如何使用 session
- 接入 mongose
實現(xiàn)圖形校驗和單點登錄
效果圖
前置條件
學習一下 nest
安裝
新建項目
npm i -g @nestjs/cli nest new project-name npm run start:dev //啟動服務
目錄結構
controllers
負責處理傳入的請求并將響應返回給客戶端。(定義路由等)
import { Controller, Get } from "@nestjs/common";@Controller()export class AppController { constructor() {} @Get() getHello(): string { return "hello world"; }}
controllers 常用裝飾器
常用裝飾器
Module
@Global()@Module({ providers: [MyService], exports: [MyService],})export class AppModule {}
- providers 屬性用來聲明模塊所提供的依賴注入 (DI) 提供者,它們將在整個模塊中共享。
- exports 屬性用于導出模塊中的提供者以供其他模塊使用。
- global 標識符用于創(chuàng)建一個全局模塊。在任何地方都可以使用 @Inject() 裝飾器來注入其提供者。
- imports 選項用于引入其他模塊中提供的依賴關系。
service
import { Injectable } from "@nestjs/common";@Injectable()export class AppService { getHello(): string { return "Hello World!"; }}
業(yè)務邏輯具體實現(xiàn)
如何生成圖形驗證碼
需要用到 svg-captcha 這個庫
npm i svg-captcha
nest 命令行創(chuàng)建一個 captcha 模塊nest g res captchanest 命令行:
import { Controller, Get, Response, Session } from "@nestjs/common";import * as svgCaptcha from "svg-captcha";@Controller("captcha")export class CaptchaController { @Get() async getCaptcha(@Response() res, @Session() session) { const captcha = svgCaptcha.create({ size: 4, noise: 2, }); session.captcha = captcha.text; res.type("svg"); res.send(captcha.data); }}
通過 session 將當前會話的 captcha 存起來此時能通過:http://localhost:3000/captcha查看到效果圖
如何使用 session
npm i express-sessionnpm i -D @types/express-session
并且再 main.ts 中引入
import * as session from "express-session";// somewhere in your initialization fileapp.use( session({ secret: "my-secret", resave: false, saveUninitialized: false, }),);
接入 mongose
在本機下載 mogodb mogodb 官網下載
安裝 mongoose
npm install --save mongoose
在 app.modele 中引入
import { Module } from "@nestjs/common";import { MongooseModule } from "@nestjs/mongoose";import { AppController } from "./app.controller";import { AppService } from "./app.service";@Module({ imports: [MongooseModule.forRoot("mongodb://127.0.0.1:27017/nest")], controllers: [AppController], providers: [AppService],})export class AppModule {}
創(chuàng)建 schemas
import { Document } from "mongoose";import * as mongoose from "mongoose";export interface User { account: string; password: string;}export interface UserDoc extends User, Document {}export const UserSchema = new mongoose.Schema({ password: { type: String, required: true }, account: { type: String, required: true, unique: true, },});export const UserModel = mongoose.model<UserDoc>("User", UserSchema);
創(chuàng)建 auth 模塊
nest g res auth
實現(xiàn)注冊和登錄方法controller
import { Controller, Get, Body, Post, UseInterceptors, Req, Request, Res,} from "@nestjs/common";import { AuthService } from "./auth.service";import { CreateUserDto } from "./dto/index";import { ApiCreatedResponse } from "@nestjs/swagger";import { CaptchaMiddleware } from "src/middleware/captcha-middleware/captcha-middleware.middleware";@Controller("auth")export class AuthController { constructor(private readonly authService: AuthService) {} @ApiCreatedResponse({ description: "The record has been successfully created.", type: CreateUserDto, }) @Post("register") async created(@Body() data: CreateUserDto) { const user = await this.authService.created(data); return user; } @UseInterceptors(CaptchaMiddleware) @Post("login") async login( @Body() data: CreateUserDto, @Req() request: Request, @Res() res, ) { const user = await this.authService.login(data, request); res.sendResponse(user); }}
引入uuid 生成隨機數和userId做鍵值對映射,為單點登錄打下基礎。
引入jwt 生成token進行校驗。
import { Injectable, UnauthorizedException } from "@nestjs/common";import { JwtService } from "@nestjs/jwt";import mongoose, { Model } from "mongoose";import { InjectModel } from "@nestjs/mongoose";import { UserDoc } from "../schemas/user.schema";import { loginMapDoc } from "../schemas/login.mapping";import { CreateUserDto } from "./dto/index";import { v4 as uuid } from "uuid";@Injectable()export class AuthService { constructor( private jwtService: JwtService, @InjectModel("user") private readonly userModel: Model<UserDoc>, @InjectModel("loginmapModel") private readonly loginmapModel: Model<loginMapDoc>, ) {} async created(data: CreateUserDto) { const user = await new this.userModel(data); return user.save(); } async login(data: any, req) { const { account, password, code } = data; if (code.toLocaleLowerCase() !== req.session?.captcha.toLocaleLowerCase()) { return {code: 400,message: "驗證碼錯誤", }; } const user = await this.userModel.findOne({ account, password, }); if (!user) { throw new UnauthorizedException(); } const loginId = uuid(); const payload = { userId: user.id, username: user.account, loginId: loginId, }; const token = this.jwtService.sign(payload); const foundCollection = await mongoose.connection.collections[ "loginmapModel" ]; if (!foundCollection) { // 如果該 collection 不存在,則創(chuàng)建它 await new this.loginmapModel(); console.log("新建成功"); } await this.loginmapModel.findOneAndUpdate( { userId: user.id }, { userId: user.id, loginId }, { upsert: true, new: true, runValidators: true }, ); return { token, loginId }; } async viladate(data: any) { const { userId, loginId } = data; const map = await this.loginmapModel.findOne({ userId, loginId }); return loginId == map.loginId; }}
最后創(chuàng)建一個guard,對用戶是否登錄進行攔截判斷
nest g gu middleware/auth
import { CanActivate, ExecutionContext, Injectable, Request, UnauthorizedException,} from "@nestjs/common";import { Reflector } from "@nestjs/core";import { JwtService } from "@nestjs/jwt";import { jwtConstants } from "@/auth/constants";import { AuthService } from "@/auth/auth.service";@Injectable()export class AuthGuardGuard implements CanActivate { constructor( private jwtService: JwtService, private reflector: Reflector, private authService: AuthService, ) {} async canActivate(context: ExecutionContext): Promise<boolean> { const skipAuth = this.reflector.get<boolean>( "skipAuth", context.getHandler(), ); // 返回 Boolean 值或 undefined,即是否跳過校驗 if (skipAuth) { return true; } const request: Request = context.switchToHttp().getRequest(); const token = this.extractTokenFromHeader(request); if (!token) { throw new UnauthorizedException(); } try { const payload = await this.jwtService.verifyAsync(token, {secret: jwtConstants.secret, }); const isRemoteLogin = await this.authService.viladate(payload); console.log(isRemoteLogin, "payload", payload); if (!isRemoteLogin) {throw new UnauthorizedException("異地登錄"); } //
標簽:
JavaScript
排行榜
