gpt4 book ai didi

authentication - NestJs 使用 jwt 和私钥和公钥进行身份验证

转载 作者:行者123 更新时间:2023-12-04 02:36:32 25 4
gpt4 key购买 nike

我正在尝试使用nestJS 了解jwt 和身份验证。
我创建了两个独立的微服务,其中一个是身份验证服务,成功登录后,客户端获取 jwt token ,并使用此 token 访问另一个微服务。

下面是 auth 服务的 JwtStrategy 和 AuthModule 的代码:

import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: 'secretKey'
});
}

async validate(payload: any) {
return payload;
}
}
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
import { PassportModule } from '@nestjs/passport';
import { LocalStrategy } from './local.strategy';
import { JwtStrategy } from './jwt.strategy';
import { JwtModule } from '@nestjs/jwt';
import { jwtConstants } from './constants';
import { AuthController } from './auth.controller';
import * as fs from 'fs';

@Module({
imports: [
UsersModule,
PassportModule,
JwtModule.register({
secret: 'secretKey',
signOptions: { expiresIn: '1h' },
}),
],
providers: [AuthService, LocalStrategy, JwtStrategy],
exports: [AuthService],
controllers: [AuthController],
})
export class AuthModule {}

这是其他服务的代码:
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: 'secretKey',
});
}

async validate(payload: any) {
return payload;
}
}

我发现对两个服务使用相同的 key 是没有意义的(因为如果我要创建 10 个微服务,我不会对所有微服务使用相同的 key )所以我使用 openssl 创建了一个私钥和公钥.
在 AuthModule 中,我复制了私钥而不是“secretKey”字符串,在其他服务中,我复制了公钥而不是“secretKey”字符串,但我收到了 401,未经授权的错误。
我在这里错过了什么?为什么 JwtStrategy 不验证公钥?

最佳答案

已经好几天了,我猜这已经解决了。我只是在这里为 future 的读者添加我的两分钱。
问题在于 JwtModule 和 JwtStrategy 实例化。它们配置不正确。您需要传入用于签名和验证 token 的算法以及 key 。要验证 token 是否实际上是使用 RS256 算法生成的,请检查 token 中的 header https://jwt.io/ .它可能会显示 HS256,因为您的代码没有使用正确的算法来签署 token 。并且在使用公钥验证 token 时失败。
要使用 RSA key 对正确生成签名 token :

  • 您需要在 signOptions 中添加算法为 RS256 并传入公众 私有(private) JwtModule 配置中的键。
  • 然后在您的服务中,您将使用 生成 token PRIVATE_KEY 当你签名时。
  • JwtStrategy 用作 guard 。它所做的只是根据配置验证 JWT。它期望 对称 key “ secret ”非对称 key 的“公共(public)部分”核实。我们必须使用 PUBLIC_KEY。您还必须在此处指定要检查验证的算法。我们必须使用 RS256 在这里也是如此,因为我们用它来生成 token 。

  • 认证模块

    @Module({
    imports: [
    ConfigModule,
    JwtModule.registerAsync({
    imports: [ConfigModule],
    useFactory: async (configService: ConfigService) => {
    const options: JwtModuleOptions = {
    privateKey: configService.get('JWT_PRIVATE_KEY'),
    publicKey: configService.get('JWT_PUB LIC_KEY'),
    signOptions: {
    expiresIn: '3h',
    issuer: '<Your Auth Service here>',
    algorithm: 'RS256',
    },
    };
    return options;
    },
    inject: [ConfigService],
    }),
    ],
    providers: [AuthService, JwtStrategy],
    exports: [AuthService],
    controllers: [AuthController],
    })
    export class AuthModule {}
    认证服务
    @Injectable()
    export class AuthService {
    constructor(
    private jwtService: JwtService,
    ) {}

    async generateToken(
    user: User,
    signOptions: jwt.SignOptions = {},
    ): Promise<AuthJwtToken> {
    const payload = { sub: user.id, email: user.email, scopes: user.roles };
    return {
    accessToken: this.jwtService.sign(payload, signOptions),
    };
    }
    }
    JwtStrategy
    @Injectable()
    export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor(private configService: ConfigService) {
    super({
    jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
    ignoreExpiration: false,
    secretOrKey: configService.get('JWT_PUBLIC_KEY'),
    algorithms: ['RS256'],
    });
    }

    async validate(payload: any) {
    const { sub: userId, email, scopes: roles } = payload;
    return {
    id: userId,
    email,
    roles,
    };
    }
    }
    在您的其他微服务中,您可以使用我们在 Auth 模块中使用的相同 JwtStrategy。
    由于您正在创建分布式应用程序,因此您需要通过手动添加 key 或使用某些 API 端点公开 key 来与其他微服务共享 PUBLIC_KEY。无论哪种方式,您都必须使用 PUBLIC_KEY 供其他服务验证。你 不得分享或公开 PRIVATE_KEY .
    注意:以下代码假定 ConfigService 将提供 RSA key 对形式 env。强烈建议不要 checkin 代码中的键。

    关于authentication - NestJs 使用 jwt 和私钥和公钥进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61606684/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com