feat: 使用 @nestjs-lib/auth 鉴权。

This commit is contained in:
Ivan Li
2021-07-18 22:40:33 +08:00
parent ec351d12f2
commit 0a03bcd36e
12 changed files with 54 additions and 133 deletions

View File

@ -1,11 +1,11 @@
import { Module } from '@nestjs/common';
import { PasswordConverter } from './services/password-converter';
import { RedisMutexModule } from './redis-mutex/redis-mutex.module';
import { JwtService } from './services/jwt.service';
import { AuthModule } from '@nestjs-lib/auth';
@Module({
providers: [PasswordConverter, JwtService],
exports: [PasswordConverter, RedisMutexModule, JwtService],
imports: [RedisMutexModule],
imports: [RedisMutexModule, AuthModule],
providers: [PasswordConverter],
exports: [PasswordConverter, RedisMutexModule],
})
export class CommonsModule {}

View File

@ -1,8 +0,0 @@
import { JwtService } from '../services/jwt.service';
import { AccountMiddleware } from './account.middleware';
describe('AccountMiddleware', () => {
it('should be defined', () => {
expect(new AccountMiddleware({} as JwtService)).toBeDefined();
});
});

View File

@ -1,31 +0,0 @@
import {
Injectable,
NestMiddleware,
UnauthorizedException,
} from '@nestjs/common';
import { JwtService } from '../services/jwt.service';
@Injectable()
export class AccountMiddleware implements NestMiddleware {
constructor(private readonly jwtService: JwtService) {}
async use(req: any, res: any, next: () => void) {
const authPayload = req.header('authorization') ?? '';
if (!authPayload) {
req.user = req.session?.user;
next();
return;
}
const token = authPayload.replace('Bearer ', '');
if (!token) {
throw new UnauthorizedException('授权凭据不合法!');
}
try {
const { payload } = await this.jwtService.verify(token);
req.user = payload;
next();
} catch (err) {
throw new UnauthorizedException('登录凭据失效或不合法!');
}
next();
}
}

View File

@ -1,59 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { generateKeyPair, KeyObject } from 'crypto';
import { getClientToken } from 'nestjs-etcd';
import { promisify } from 'util';
import { JwtService } from './jwt.service';
import { SignJWT } from 'jose/jwt/sign';
describe('JwtService', () => {
let service: JwtService;
let privateKey: KeyObject;
let publicKey: KeyObject;
beforeAll(async () => {
const pair = await promisify(generateKeyPair)('ec', {
namedCurve: 'prime256v1',
});
privateKey = pair.privateKey;
publicKey = pair.publicKey;
});
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
JwtService,
{
provide: getClientToken(),
useValue: {
get: () => ({
buffer: () =>
Promise.resolve(
publicKey.export({ format: 'pem', type: 'spki' }),
),
}),
},
},
],
}).compile();
service = module.get<JwtService>(JwtService);
await service.onModuleInit();
});
it('should be defined', () => {
expect(service).toBeDefined();
});
describe('verify', () => {
it('normal', async () => {
const token = await new SignJWT({ userId: 'test' })
.setProtectedHeader({ alg: 'ES256' })
.setIssuedAt()
.setIssuer('urn:example:issuer')
.setAudience('urn:example:audience')
.setExpirationTime('1h')
.sign(privateKey);
await expect(service.verify(token)).resolves.toBeTruthy();
});
});
});

View File

@ -1,23 +0,0 @@
import { OnModuleInit } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { KeyObject, createPublicKey } from 'crypto';
import { jwtVerify } from 'jose/jwt/verify';
import { Etcd3, InjectClient } from 'nestjs-etcd';
@Injectable()
export class JwtService implements OnModuleInit {
publicKey: KeyObject;
constructor(@InjectClient() private readonly etcd: Etcd3) {}
async onModuleInit() {
const buff = await this.etcd
.get('commons/auth-jwt-public-key/index')
.buffer();
this.publicKey = createPublicKey(buff);
}
async verify(token: string) {
return await jwtVerify(token, this.publicKey, {
algorithms: ['PS256', 'ES256'],
});
}
}