如何用NestJS实现长尾词校验和单点登录功能?

2026-03-31 15:001阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1427个文字,预计阅读时间需要6分钟。

如何用NestJS实现长尾词校验和单点登录功能?

目录+实现图形界面和单点登录+预设条件+安装+Module service+如何生成图形验证码+如何使用session+接入mongose+实现图形验证码和单点登录+效果图+预设条件+学习一下+Nest+安装+新建项目+npm+i

目录
  • 实现图形校验和单点登录
  • 前置条件
    • 安装
    • Module
    • service
  • 如何生成图形验证码
    • 如何使用 session
  • 接入 mongose

    实现图形校验和单点登录

    效果图

    前置条件

    学习一下 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 常用装饰器

    常用装饰器

    @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 命令行:

    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 存起来此时能通过:localhost:3000/captcha查看到效果图

    如何使用 session

    npm i express-session npm i -D @types/express-session

    并且再 main.ts 中引入

    如何用NestJS实现长尾词校验和单点登录功能?

    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('异地登录'); } //

    标签:示例

    本文共计1427个文字,预计阅读时间需要6分钟。

    如何用NestJS实现长尾词校验和单点登录功能?

    目录+实现图形界面和单点登录+预设条件+安装+Module service+如何生成图形验证码+如何使用session+接入mongose+实现图形验证码和单点登录+效果图+预设条件+学习一下+Nest+安装+新建项目+npm+i

    目录
    • 实现图形校验和单点登录
    • 前置条件
      • 安装
      • Module
      • service
    • 如何生成图形验证码
      • 如何使用 session
    • 接入 mongose

      实现图形校验和单点登录

      效果图

      前置条件

      学习一下 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 常用装饰器

      常用装饰器

      @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 命令行:

      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 存起来此时能通过:localhost:3000/captcha查看到效果图

      如何使用 session

      npm i express-session npm i -D @types/express-session

      并且再 main.ts 中引入

      如何用NestJS实现长尾词校验和单点登录功能?

      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('异地登录'); } //

      标签:示例