中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

nestjs實現圖形校驗和單點登錄的方法

發布時間:2023-10-20 09:48:45 來源:億速云 閱讀:91 作者:栢白 欄目:開發技術

本篇文章和大家了解一下nestjs實現圖形校驗和單點登錄的方法。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有所幫助。

實現圖形校驗和單點登錄

效果圖

nestjs實現圖形校驗和單點登錄的方法

前置條件

學習一下 nest

安裝

新建項目

 npm i -g @nestjs/cli
 nest new project-name
 npm run start:dev //啟動服務

目錄結構

nestjs實現圖形校驗和單點登錄的方法

controllers

負責處理傳入的請求并將響應返回給客戶端。(定義路由等)

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)響應體(res)session獲取 req.params 參數獲取 req.body 參數獲取 req.query 參數獲取 req.headers 參數

Module

@Global()
@Module({
  providers: [MyService],
  exports: [MyService],
})
export class AppModule {}
  • providers 屬性用來聲明模塊所提供的依賴注入 (DI) 提供者,它們將在整個模塊中共享。

  • exports 屬性用于導出模塊中的提供者以供其他模塊使用。

  • global 標識符用于創建一個全局模塊。在任何地方都可以使用 @Inject() 裝飾器來注入其提供者。

  • imports 選項用于引入其他模塊中提供的依賴關系。

service

import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

業務邏輯具體實現

如何生成圖形驗證碼

需要用到 svg-captcha 這個庫

npm i svg-captcha

nest 命令行創建一個 captcha 模塊nest g res captchanest 命令行:

nestjs實現圖形校驗和單點登錄的方法

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查看到效果圖

nestjs實現圖形校驗和單點登錄的方法

如何使用 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

在本機下載 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 {}

創建 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);

創建 auth 模塊

nest g res auth

實現注冊和登錄方法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 不存在,則創建它
      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;
  }
}

最后創建一個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('異地登錄');
      }
      // ???? 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;
  }
}

以上就是nestjs實現圖形校驗和單點登錄的方法的簡略介紹,當然詳細使用上面的不同還得要大家自己使用過才領會。如果想了解更多,歡迎關注億速云行業資訊頻道哦!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

丰宁| 讷河市| 晋宁县| 自治县| 闸北区| 仙游县| 郑州市| 南昌市| 建昌县| 新宾| 佛冈县| 宁乡县| 平顺县| 雅安市| 三门县| 昭通市| 晋城| 遂川县| 六枝特区| 曲阜市| 延津县| 临桂县| 德格县| 容城县| 巴中市| 雷波县| 普定县| 余庆县| 丹江口市| 上犹县| 尚志市| 淅川县| 陈巴尔虎旗| 神池县| 保定市| 平安县| 韶山市| 兰坪| 民乐县| 浦江县| 盐津县|