nestjs實現(xiàn)圖形校驗和單點登錄的示例代碼
實現(xiàn)圖形校驗和單點登錄
效果圖
前置條件
學(xué)習(xí)一下 nest
安裝
新建項目
npm i -g @nestjs/cli nest new project-name npm run start:dev //啟動服務(wù)
目錄結(jié)構(gòu)
controllers
負(fù)責(zé)處理傳入的請求并將響應(yīng)返回給客戶端。(定義路由等)
import { Controller, Get } from '@nestjs/common'; @Controller() export class AppController { constructor() {} @Get() getHello(): string { return 'hello world'; } }
controllers 常用裝飾器
常用裝飾器
@Controller(path) | @Get(path) | @Post(path) | @Request(), @Req() | @Response(), @Res() | @Session() | @Param(key?: string) | @Body(key?: string) | @Query(key?: string) | @Headers(name?: string) |
---|---|---|---|---|---|---|---|---|---|
定義 root 路徑 | 定義 get 請求和路徑 | 定義 post 請求和路徑 | 請求體(req) | 響應(yīng)體(res) | session | 獲取 req.params 參數(shù) | 獲取 req.body 參數(shù) | 獲取 req.query 參數(shù) | 獲取 req.headers 參數(shù) |
Module
@Global() @Module({ providers: [MyService], exports: [MyService], }) export class AppModule {}
- providers 屬性用來聲明模塊所提供的依賴注入 (DI) 提供者,它們將在整個模塊中共享。
- exports 屬性用于導(dǎo)出模塊中的提供者以供其他模塊使用。
- global 標(biāo)識符用于創(chuàng)建一個全局模塊。在任何地方都可以使用 @Inject() 裝飾器來注入其提供者。
- imports 選項用于引入其他模塊中提供的依賴關(guān)系。
service
import { Injectable } from '@nestjs/common'; @Injectable() export class AppService { getHello(): string { return 'Hello World!'; } }
業(yè)務(wù)邏輯具體實現(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 將當(dāng)前會話的 captcha 存起來此時能通過:http://localhost:3000/captcha查看到效果圖
如何使用 session
npm i express-session npm i -D @types/express-session
并且再 main.ts 中引入
import * as session from 'express-session'; // somewhere in your initialization file app.use( session({ secret: 'my-secret', resave: false, saveUninitialized: false, }), );
接入 mongose
在本機(jī)下載 mogodb mogodb 官網(wǎng)下載
安裝 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 生成隨機(jī)數(shù)和userId做鍵值對映射,為單點登錄打下基礎(chǔ)。
引入jwt 生成token進(jìn)行校驗。
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,對用戶是否登錄進(jìn)行攔截判斷
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('異地登錄'); } // ?? We're assigning the payload to the request object here // so that we can access it in our route handlers request['user'] = payload; } catch { throw new UnauthorizedException(); } return true; } private extractTokenFromHeader(request: any): string | undefined { const [type, token] = request.headers.authorization?.split(' ') ?? []; return type === 'Bearer' ? token : undefined; } }
到此這篇關(guān)于nestjs實現(xiàn)圖形校驗和單點登錄的示例代碼的文章就介紹到這了,更多相關(guān)nestjs 圖形校驗和單點登錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript搜索框點擊文字消失失焦時文本出現(xiàn)
這篇文章主要介紹了javascript實現(xiàn)搜索框點擊文字消失失焦時文本出現(xiàn)的效果,示例代碼如下,大家可以看看2014-09-09JavaScript使用小插件實現(xiàn)倒計時的方法講解
今天小編就為大家分享一篇關(guān)于JavaScript使用小插件實現(xiàn)倒計時的方法講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-039個讓JavaScript調(diào)試更簡單的Console命令
這篇文章主要為大家詳細(xì)介紹了9個讓JavaScript調(diào)試更簡單的Console命令,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-11-11在chrome瀏覽器中,防止input[text]和textarea在聚焦時出現(xiàn)黃色邊框的解決方法
chrome瀏覽器不管對于開發(fā)者還是一般用戶都可以說是一個相當(dāng)優(yōu)秀的網(wǎng)頁瀏覽器,但是在開發(fā)中,讓人感覺很多余的一個特性就是,在表單項中的控件聚焦時總會出現(xiàn)一個黃色邊框2011-05-05JavaScript中的構(gòu)造函數(shù)和實例對象之間的關(guān)系(構(gòu)造器)
這篇文章主要介紹了JavaScript中的構(gòu)造函數(shù)和實例對象之間的關(guān)系(構(gòu)造器),需要的朋友可以參考下2023-05-05Bootstrap網(wǎng)頁布局網(wǎng)格的實現(xiàn)
柵格就是網(wǎng)格,本文詳細(xì)的介紹了Bootstrap網(wǎng)頁布局網(wǎng)格的原理和實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07