Nest.js学习之路(25)-JSON Web Token(JWT)保护API Endpoint-使用Passport

这一章要来练习使用JWT来保护API Enpoint

流程大致为:

  1. 安装套件
  2. 取得token
  3. 新增jwtStrategy
  4. 设定defaultStrategy
  5. 测试

安装套件

yarn add @nestjs/jwt passport-jwt @types/passport-jwt

其中@nestjs/jwt是个工具套件,结合nestjs Module设定概念和jsonwebtoken套件,可以少一点coding(但不是太多)

如何产生token

我们需要建立auth controller,

import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';

@Controller('auth')
export class AuthController {
    constructor(private readonly authService: AuthService){}
    // 传入name及password取得jwt token
    @Post('getToken')
    getTokenByUserId(
            @Body('name') name: string,
            @Body('password') password: string,
    ){
      return this.authService.createToken(name, password);
    }
}

改写auth service

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { UserService } from 'feature/user/user.service';
import { JwtService} from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(
      // 注入UsersService,所以需要import UsersModule
      // 底下的provider才能被注入
            private readonly usersService: UserService,
            private readonly jwtService: JwtService,
  ) {}

    async createToken(name: string, password: string) {

        // 验证使用者,用最简单举例
        if (name !== password) {
            throw new UnauthorizedException();
        }

        const user = { name };
        const expiration = 60 * 60;
        // 将使用者资讯加密
        const accessToken = this.jwtService.sign(user, {
            // 关于建立token时相关参数
            // 过期时间
            expiresIn: expiration,
            // issuer:'http://iron-nest.org',
            // algorithm:'RS256', // default是HMAC SHA256,也可以指定別的
        });

        return {
            expiration,
            accessToken,
        };

    }

  async validateUser(payload) {
    // jwt decoded后会得到上面的user object
    return await this.usersService.findOneByName(payload.name);
  }
}

新增findOneByName在user service

async findOneByName(name) {
    return await this.em.createQueryBuilder(User, 'u')
        .leftJoinAndSelect('u.roles', 'r')
        .where('u.name = :name', {name})
        .getOne();
}

如何验证token

验证token需要用到passport-jwt套件,里面已经帮我们写好如何验证,我们只要知道怎么用就可以了

jwtStrategy,大致跟http-bearer一样,不同的是super()要传入

  • token
  • 相关资讯,key、issuer等
import { ExtractJwt, Strategy } from 'passport-jwt';

import { AuthService } from './auth.service';
import { Injectable, UnauthorizedException, Logger } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor(private readonly authService: AuthService) {
        super({
            // 这里没有intellisense可以用,下面这一段是说
            // 要从header取得bearer token
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            // 这里的key就是要跟create token时的key一样
            secretOrKey: 'geekjc-demo',
            issuer: 'https://www.geekjc.com',
        });
    }

    // Passport会自动verify jwt,如果key不正确,或是相关信息
    // 不正确,如issuer
    async validate(payload){
        const user = await this.authService.validateUser(payload);
        if (!user) throw new UnauthorizedException();
        return user;
    }

}

接着到auth module更新imports、controllers、providers

import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { UserModule } from 'feature/user/user.module';
import { AuthService } from './auth.service';
import { HttpStrategy } from './http.strategy';
import { AuthController } from './auth.controller';
import { JwtStrategy } from './jwt.strategy';

@Module({
    imports: [
        // 建立jsonwebtoken时的相关信息
        JwtModule.register({
            secretOrPrivateKey: 'geekjc-demo',
            // signOption可以在JwtModule设定
            // 或是在createToken时候设定
            signOptions: {
                // expiresIn: 3600,
                issuer: 'https://www.geekj.com',
            },
        }),
        UserModule],
    providers: [AuthService, HttpStrategy, JwtStrategy],
    controllers: [AuthController],
})
export class AuthModule {}

设定defaultStrategy

上一章用@AuthGuard()要传入Strategy名称,通过PassportModule.register可以设定defaultStrategy,
在该module下就不用每次都要指定Strategy,除非是例外

@Module({
  imports: [
        // PassportModule.register({defaultStrategy: 'bearer'})
        // 指定strategy, 不用再AuthGuard里特别指定
        PassportModule.register({defaultStrategy: 'jwt'}),
        TypeOrmModule.forFeature([User, Platform, Role]),
    ],
  providers: [UserService, PlatformService, RoleService],
    controllers: [UserController],
    exports: [UserService],
})
export class UserModule {}

修改Users Controller把AuthGuard参数拿掉

@UseGuards(AuthGuard())
@Controller('users')
export class UsersController {
...
}

测试
错误token


Nest.js学习之路(25)-JSON Web Token(JWT)保护API Endpoint-使用Passport_第1张图片
2018112301.png

取得Token


Nest.js学习之路(25)-JSON Web Token(JWT)保护API Endpoint-使用Passport_第2张图片
2018112302.png

指定Authorization token


Nest.js学习之路(25)-JSON Web Token(JWT)保护API Endpoint-使用Passport_第3张图片
2018112303.png

推荐一下我的公众号: 【 geekjc 】,微信号: 【 c8706288 】一起学习交流编程知识,分享经验,各种有趣的事。

Nest.js学习之路(25)-JSON Web Token(JWT)保护API Endpoint-使用Passport_第4张图片
tuiguang.png

你可能感兴趣的:(Nest.js学习之路(25)-JSON Web Token(JWT)保护API Endpoint-使用Passport)