【问题标题】:Nestjs prod jwt auth work on local but not in serverNestjs prod jwt auth 在本地工作,但不在服务器上工作
【发布时间】:2020-02-22 14:35:43
【问题描述】:

这篇文章已经被编辑了好几次,所以我用更相关的方式重写了这篇文章

[!] 我所有的代码都是股票here,请参阅master 分支。请记住:代码在本地工作,但不在我的服务器上。

Tl;博士

在本地(start:devstart:prod)一切正常,在我的服务器(start:devstart:prod)我的 jwt 验证不起作用。我拿回了令牌,但如果我在受保护的路线上测试它,我得到了一个 401...

日志

一些日志(在产品中)。

1 - 我在domain.dev/api/hello 中发送了一个获取请求(通过邮递员)

Request Headers
  User-Agent: "PostmanRuntime/7.19.0"
  Accept: "*/*"
  Cache-Control: "no-cache"
  Postman-Token: "3940ba0e-3c60-4746-bb12-e06bf01df0bf"
  Host: "domain.dev"
  Accept-Encoding: "gzip, deflate"
  Connection: "keep-alive"
Response Headers
  Date: "Sun, 27 Oct 2019 20:54:35 GMT"
  Server: "Apache/2.4.25 (Debian)"
  X-Powered-By: "Express"
  Access-Control-Allow-Origin: "*"
  Content-Type: "text/html; charset=utf-8"
  Content-Length: "12"
  ETag: "W/"c-Lve95gjOVATpfV8EL5X4nxwjKHE""
  Keep-Alive: "timeout=5, max=100"
  Connection: "Keep-Alive"
Response Body
  Hello World!

服务器响应,好的!

2 - 我在domain.dev/api/auth 中发送一个帖子请求(通过邮递员)

Request Headers
  Content-Type: "application/json"
  User-Agent: "PostmanRuntime/7.19.0"
  Accept: "*/*"
  Cache-Control: "no-cache"
  Postman-Token: "4391992e-788c-4780-b188-833999383704"
  Host: "alanbouteiller.dev"
  Accept-Encoding: "gzip, deflate"
  Content-Length: 45
  Connection: "keep-alive"
Request Body
  name: "Hadock"
  password: "XXXXXX"
Response Headers
  Date: "Sun, 27 Oct 2019 20:57:14 GMT"
  Server: "Apache/2.4.25 (Debian)"
  X-Powered-By: "Express"
  Access-Control-Allow-Origin: "*"
  Content-Type: "application/json; charset=utf-8"
  Content-Length: "212"
  ETag: "W/"d4-XWUV7P7Ft81OyIDhImoZoNDfnsA""
  Keep-Alive: "timeout=5, max=100"
  Connection: "Keep-Alive"
Response Body
  access_token: 
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSGFkb2NrIiwic3ViIjoiNWQ4YTFmZGIyMDc3NTU0NjlmMjgzNDNlIiwiaWF0IjoxNTcyMjEwMDY3LCJleHAiOjE1NzIyMTAxODd9.hoe69wy86XXXXXXXXXXXXXghGVw8TEKmOA"

服务器向我发送此日志(通过 pm2):

代码中每条日志对应:

  • 红色 -> auth.controller.ts
// give the jwt
@Post()
async login(@Request() req): Promise<any> {
    console.log(req.body); // the red
    return await this.authService.login(req.body);
}
  • 橙绿蓝紫->auht.service.ts
@Injectable()
export class AuthService {
    constructor(
        @InjectModel('Author') private readonly authorModel: Model<AuthorInterface>,
        private readonly authorService: AuthorService,
        private readonly jwtService: JwtService,
    ) {}

    // check if user exist in db, if is return user
    async validateUser(name: string): Promise<any> {
        const user = await this.authorService.getAuthorByName(name);
        console.log(user); // orange 1
        if (user.length !== 0) {
            console.log({status: true, data: user[0]}); // orange 2
            return {status: true, data: user[0]};
        } else {
            return {status: false, data: 'no user with this name'};
        }
    }

    // check user and return token if user is valid
    async login(author: any) {
        const check = await this.validateUser(author.name);
        console.log(check); // orange 3
        if (check.status) {
            console.log(author.password); // green
            console.log(check.data.password); // green
            const compare = await bcrypt.compare(author.password, check.data.password);
            if (!compare) {
                // if check is not ok
                return {status: false, message: 'bad credential'};
            } else {
                // generate jwt payload
                const payload = {name: author.name, sub: check.data._id};
                console.log(payload); // blue
                const jwt = this.jwtService.sign(payload);
                console.log(jwt); // purple
                // save in db
                await this.authorModel.updateOne({_id: check.data._id}, {$set: {token: jwt}});
                // return
                return {access_token: jwt};
            }
        } else {
            return {status: false, message: 'no user found'};
        }
    }
}

一切看起来都不错...令牌在 db 和响应中是相同的。

但是;我在jwt.strategy.ts 中验证的函数永远不会被调用:

import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy} from '@nestjs/passport';
import {Injectable, UnauthorizedException} from '@nestjs/common';
import { ConfigService } from '../conf/config.service';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor(env: ConfigService) {
        super({
            // which the jwt is extracted
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            // the password module check the expiration, this class no
            ignoreExpiration: false,
            secretOrKey: env.get('secret'),
        });
    }

    // this function is call automatically by the @UseGuards(AuthGuard('jwt'))
    async validate(payload: any) {
        console.log('----------validate');
        console.log(payload);
        console.log({ username: payload.name, userId: payload.sub, timeStamp: new Date() });
        return !payload ? new UnauthorizedException() : { username: payload.name, userId: payload.sub, timeStamp: new Date() };
    }
}

console.log 在日志中不可见,而在本地使用相同的文件时会出现这种情况:

// LOCAL LOG WHIT THE SAME BUILD FOLDER
{ name: 'hadock', password: 'test' }
[
  {
    _id: 5d7e6520c7e8fb43fcb1a1e5,
    name: 'hadock',
    password: '$2b$12$f8bUfYwr7jjPlDuIrKVtzuKMZRVVRWjUUIOJpdSaeoFv4PN5XQ57q',
    __v: 0,
    token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaGFkb2NrIiwic3ViIjoiNWQ3ZTY1MjBjN2U4ZmI0M2ZjYjFhMWU1IiwiaWF0IjoxNTcyMTc2ODkxLCJleHAiOjE1NzIxNzcwMTF9.8RnXXXXXXXX2rjwXs'
  }
]
{
  status: true,
  data: {
    _id: 5d7e6520c7e8fb43fcb1a1e5,
    name: 'hadock',
    password: '$2b$12$f8bUfYwr7jjPlDuIrKVtzuKMZRVVRWjUUIOJpdSaeoFv4PN5XQ57q',
    __v: 0,
    token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaGFkb2NrIiwic3ViIjoiNWQ3ZTY1MjBjN2U4ZmI0M2ZjYjFhMWU1IiwiaWF0IjoxNTcyMTc2ODkxLCJleHAiOjE1NzIxNzcwMTF9.8RnXXXXXXXX2rjwXs'
  }
}
{
  status: true,
  data: {
    _id: 5d7e6520c7e8fb43fcb1a1e5,
    name: 'hadock',
    password: '$2b$12$f8bUfYwr7jjPlDuIrKVtzuKMZRVVRWjUUIOJpdSaeoFv4PN5XQ57q',
    __v: 0,
    token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaGFkb2NrIiwic3ViIjoiNWQ3ZTY1MjBjN2U4ZmI0M2ZjYjFhMWU1IiwiaWF0IjoxNTcyMTc2ODkxLCJleHAiOjE1NzIxNzcwMTF9.8RnXXXXXXXX2rjwXs'
  }
}
test
$2b$12$f8bUfYwr7jjPlDuIrKVtzuKMZRVVRWjUUIOJpdSaeoFv4PN5XQ57q
{ name: 'hadock', sub: 5d7e6520c7e8fb43fcb1a1e5 }
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaGFkb2NrIiwic3ViIjoiNWQ3ZTY1MjBjN2U4ZmI0M2ZjYjFhMWU1IiwiaWF0IjoxNTcyMjEyNDI5LCJleHAiOjE1NzIyMTI1NDl9.MrjXXXXXXXXX4NLFNw
----------validate
{
  name: 'hadock',
  sub: '5d7e6520c7e8fb43fcb1a1e5',
  iat: 1572212429,
  exp: 1572212549
}
{
  username: 'hadock',
  userId: '5d7e6520c7e8fb43fcb1a1e5',
  timeStamp: 2019-10-27T21:40:47.206Z
}

【问题讨论】:

    标签: server jwt nestjs


    【解决方案1】:

    我相信您需要分享更多代码,但无论如何我都会加我的 2 美分。在这里,我们看到您正在添加一堆 CORS 标头,这很好,看起来它们不是必需的,因为您使用反向代理访问同一个 Web 服务器。现在,您的问题似乎与您的应用程序的 JWT 验证部分有关。

    通常,对于 JWT 身份验证,身份验证服务器(您的 API)会创建一个带有密钥的 JWT(对称或非对称)并将其返回给消费者以供将来的 API 调用使用。我看到您通过 Authorization 标头正确传递了它。现在,您的问题可能在验证的后端。您需要的是一个中间件,它检查 Authorization 标头,删除它的 Bearer 部分,包括空间,然后它使用您的公钥(非对称)或私钥(对称)并计算是否不是有效的 JWT,如果有效则继续,否则拒绝。

    请随时在这里回复,我会尽可能回复。你肯定需要分享你的整个请求和 chrome 记录的整个响应,检查网络标签。

    【讨论】:

    • 嗨,如果我在本地使用我的 nestjs 应用程序(通过 yarn start:prod 就像在我的服务器中一样),我的所有路由都可以正常工作。所以我想我的令牌验证也可以正常工作,不是吗?
    • @Hadock 发布检查 JWT 以查看其是否有效的中间件代码。另外,在此处放置一些日志以确定比较的结果。
    • 我添加了一些日志 =)
    猜你喜欢
    • 2019-03-16
    • 1970-01-01
    • 2021-10-01
    • 2020-01-25
    • 2023-01-02
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多