Nestjs学习 day10

110 阅读2分钟

1.加密工具函数


import * as crypto from 'crypto';

/**

* Make salt

*/

export function makeSalt(): string {

    return crypto.randomBytes(3).toString('base64');

}

/**

* Encrypt password

* @param password 密码

* @param salt 密码盐

*/

export function encryptPassword(password: string, salt: string): string {

    if (!password || !salt) {

        return '';

    }

    const tempSalt = Buffer.from(salt, 'base64');

    return (

        // 10000 代表迭代次数 16代表长度

        crypto.pbkdf2Sync(password, tempSalt, 10000, 16, 'sha1').toString('base64')

    );

}

2.查询用户信息


// src/logical/user/user.service.ts

import { Injectable } from '@nestjs/common';

import * as Sequelize from 'sequelize'; // 引入 Sequelize 库

import sequelize from '../../database/sequelize'; // 引入 Sequelize 实例

@Injectable()

export class UserService {

    /**

    * 查询是否有该用户

    * @param username 用户名

    */

    async findOne(username: string): Promise<any | undefined> {

        const sql = `

            SELECT

            user_id userId, account_name username, real_name realName, passwd

            password,

            passwd_salt salt, mobile, role

            FROM

            admin_user

            WHERE

            account_name = '${username}'

            `; // 一段平淡无奇的 SQL 查询语句

        try {

            const user = (

                await sequelize.query(sql, {

                    type: Sequelize.QueryTypes.SELECT, // 查询方式

                    raw: true, // 是否使用数组组装的方式展示结果

                    logging: true, // 是否将 SQL 语句打印到控制台

                })

            )[0];

            // 若查不到用户,则 user === undefined

            return user;

        } catch (error) {

            console.error(error);

            return void 0;

        }

    }

3.注册用户


import { Injectable } from '@nestjs/common';

import * as Sequelize from 'sequelize'; // 引入 Sequelize 库

import sequelize from '../../database/sequelize'; // 引入 Sequelize 实例

import { makeSalt, encryptPassword } from '../../utils/cryptogram'; // 引入加密函数

@Injectable()

export class UserService {

    /**

    * 查询是否有该用户

    * @param username 用户名

    */

    async findOne(username: string): Promise<any | undefined> {}

    /**

    * 注册

    * @param requestBody 请求体

    */

    async register(requestBody: any): Promise<any> {

        const { accountName, realName, password, repassword, mobile } = requestBody;

        if (password !== repassword) {

            return {

                code: 400,

                msg: '两次密码输入不一致',

            };

        }

        const user = await this.findOne(accountName);

        if (user) {

            return {

                code: 400,

                msg: '用户已存在',

            };

        }

        const salt = makeSalt(); // 制作密码盐

        const hashPwd = encryptPassword(password, salt); // 加密密码

        const registerSQL = `

            INSERT INTO admin_user

            (account_name, real_name, passwd, passwd_salt, mobile, user_status,

            role, create_by)

            VALUES

            ('${accountName}', '${realName}', '${hashPwd}', '${salt}', '${mobile}',

            1, 3, 0)

        `;



        try {

            await sequelize.query(registerSQL, { logging: false });

            return {

                code: 200,

                msg: 'Success',

            };

        } catch (error) {

            return {

                code: 503,

                msg: `Service error: ${error}`,

            };

        }

    }

}

4.路由访问


// src/logical/user/user.controller.ts

import { Controller, Post, Body } from '@nestjs/common';

import { UserService } from './user.service';

@Controller('user')

export class UserController {

    constructor(private readonly usersService: UserService) { }

    // @Post('find-one')

    // findOne(@Body() body: any) {

    // return this.usersService.findOne(body.username);

    // }

    @Post('register')

    async register(@Body() body: any) {

        return await this.usersService.register(body);

    }

}

5.安装jwt,jwt登录使用

yarn add passport passport-jwt passport-local @nestjs/passport @nestjs/jwt -S


nest g service auth logical

nest g module auth logical


// src/logical/auth/constats.ts

export const jwtConstants = {

  secret: 'shinobi7414', // 秘钥

};


// src/logical/auth/jwt.strategy.ts

import { ExtractJwt, Strategy } from 'passport-jwt';

import { PassportStrategy } from '@nestjs/passport';

import { Injectable } from '@nestjs/common';

import { jwtConstants } from './constants';

@Injectable()

export class JwtStrategy extends PassportStrategy(Strategy) {

    constructor() {

        super({

            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),

            ignoreExpiration: false,

            secretOrKey: jwtConstants.secret,

        });

    }

    // JWT验证 - Step 4: 被守卫调用

    async validate(payload: any) {

        console.log(`JWT验证 - Step 4: 被守卫调用`);

        return {

            userId: payload.sub,

            username: payload.username,

            realName: payload.realName,

            role: payload.role,

        };

    }

}


// src/logical/auth/auth.service.ts

import { Injectable } from '@nestjs/common';

import { UserService } from '../user/user.service';

import { JwtService } from '@nestjs/jwt';

import { encryptPassword } from '../../utils/cryptogram';

@Injectable()

export class AuthService {

    constructor(

        private readonly usersService: UserService,

        private readonly jwtService: JwtService,

    ) { }

    // JWT验证 - Step 2: 校验用户信息

    async validateUser(username: string, password: string): Promise<any> {

        console.log('JWT验证 - Step 2: 校验用户信息');

        const user = await this.usersService.findOne(username);

        if (user) {

            const hashedPassword = user.password;

            const salt = user.salt;

            // 通过密码盐,加密传参,再与数据库里的比较,判断是否相等

            const hashPassword = encryptPassword(password, salt);

            if (hashedPassword === hashPassword) {

                // 密码正确

                return {

                    code: 1,

                    user,

                };

            } else {

                // 密码错误

                return {

                    code: 2,

                    user: null,

                };

            }

        }

        // 查无此人

        return {

            code: 3,

            user: null,

        };

    }

    async certificate(user: any) {

        const payload = {

            username: user.username,

            sub: user.userId,

            realName: user.realName,

            role: user.role,

        };

        console.log('JWT验证 - Step 3: 处理 jwt 签证');

        try {

            const token = this.jwtService.sign(payload);

            return {

                code: 200,

                data: {

                    token,

                },

                msg: `登录成功`,

            };

        } catch (error) {

            return {

                code: 600,

                msg: `账号或密码错误`,

            };

        }

    }

}


// src/logical/auth/local.strategy.ts

import { Strategy } from 'passport-local';

import { PassportStrategy } from '@nestjs/passport';

import { Injectable, UnauthorizedException } from '@nestjs/common';

import { AuthService } from './auth.service';

@Injectable()

export class LocalStrategy extends PassportStrategy(Strategy) {

    constructor(private readonly authService: AuthService) {

        super();

    }

    async validate(username: string, password: string): Promise<any> {

        const user = await this.authService.validateUser(username, password);

        if (!user) {

            throw new UnauthorizedException();

        }

        return user;

    }

}


// src/logical/auth/auth.module.ts

import { Module } from '@nestjs/common';

import { AuthService } from './auth.service';

import { LocalStrategy } from './local.strategy';

import { JwtStrategy } from './jwt.strategy';

import { UserModule } from '../user/user.module';

import { PassportModule } from '@nestjs/passport';

import { JwtModule } from '@nestjs/jwt';

import { jwtConstants } from './constants';

@Module({

    imports: [

        PassportModule.register({ defaultStrategy: 'jwt' }),

        JwtModule.register({

            secret: jwtConstants.secret,

            signOptions: { expiresIn: '8h' }, // token 过期时效

        }),

        UserModule,

    ],

    providers: [AuthService, LocalStrategy, JwtStrategy],

    exports: [AuthService],

})

export class AuthModule { }


// src/app.module.ts