如何使用打字稿通过`jsonwebtoken`获取令牌到期

Posted

技术标签:

【中文标题】如何使用打字稿通过`jsonwebtoken`获取令牌到期【英文标题】:How to get token expiration with `jsonwebtoken` using typescript 【发布时间】:2018-05-10 13:02:50 【问题描述】:

我正在使用jsonwebtoken 来解码令牌,并且正在尝试获取到期日期。 Typescript 抛出关于 exp 属性的错误,我不太确定如何解决它们:

import jwt from 'jsonwebtoken'

const tokenBase64 = 'ey...' /* some valid token */

const token = jwt.decode(tokenBase64)
const tokenExpirationDate = token.exp
//                                ^^^
// Property 'exp' does not exist on type 'string | object'. Property 'exp' does not exist on type 'string'.

我已经安装了@types/jsonwebtoken,并寻找一个令牌类型来转换token,但没有找到。有什么建议吗?

使用

@types/jsonwebtoken@7.2.3 jsonwebtoken@8.1.0

.tsconfig:


  "compilerOptions": 
    "allowJs": true,
    "baseUrl": ".",
    "jsx": "Preserve",
    "moduleResolution": "Node",
    "module": "ESNext",
    "sourceMap": true,
    "removeComments": true,
    "allowSyntheticDefaultImports": true,
    "target": "ESNext"
  

【问题讨论】:

【参考方案1】:

当我使用import jwt from 'jsonwebtoken' 行时,我收到了相同的错误消息 使用var jwt = require('jsonwebtoken'); [1] 可以正常工作:

var jwt = require('jsonwebtoken');
var tokenBase64 = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZXhwIjoiMTUxMTk1MDcwMyIsImFkbWluIjp0cnVlfQ.wFC-9ZsqA9QuvLkRSkQmVYpUmgH9R-j8M4D0GECuPHY';

const token = jwt.decode(tokenBase64);
const tokenExpirationDate = token.exp
console.log(tokenExpirationDate);

[1] 另见https://github.com/auth0/node-jsonwebtoken

【讨论】:

感谢您更新您的问题。问题是由import jwt from 'jsonwebtoken' 引起的。我相应地更新了我的答案。希望它对你有用。如果您遇到无法找到需要的错误,请执行npm install @types/node --save-dev,请参阅***.com/questions/31173738/… 这行得通,但如果有人有一个仍然可以使用 import 而不是 require 的解决方案,那就太好了。也许应该更改类型文件。【参考方案2】:

我发现用户导入的唯一方法是:

import  sign, verify  from 'jsonwebtoken';
sign('Hello', 'secret');

但我认为require 方法更好,这样您就不必显式导入每个函数。

【讨论】:

实现你的答案后这个错误怎么样? Argument of type 'string | undefined' is not assignable to parameter of type 'Secret''有什么想法吗? @chris 我发现摆脱ts Argument of type 'string | undefined' is not assignable to parameter of type 'Secret 的唯一方法是创建自己的类型定义。关于密钥,我必须执行以下操作ts // eslint-disable-next-line no-unused-vars declare namespace NodeJS export interface ProcessEnv JWT_SECRET: string, JWT_EXPIRATION: string, TOKEN_ISSUER: string 【参考方案3】:

从 jsonwebtoken 8.3 开始,jsonwebtoken.decode() 具有以下类型定义:

export function decode(
    token: string,
    options?: DecodeOptions,
): null |  [key: string]: any  | string;

由于 Typescript 无法推断出正确的类型且 exp 未知,因此最简单的方法是将结果强制转换为 any

import jwt from 'jsonwebtoken'

const tokenBase64 = 'ey...' /* some valid token */

const token: any = jwt.decode(tokenBase64)
const tokenExpirationDate = token.exp

【讨论】:

我遇到了这个问题:模块 '"./node_modules/@types/jsonwebtoken/index"' 没有默认导出。【参考方案4】:

这就是我使用 TS 解码的方式

import jwt from 'jsonwebtoken';

export const isTokenExpired = (token: string): boolean => 
    try 
        const  exp  = jwt.decode(token) as 
            exp: number;
        ;
        const expirationDatetimeInSeconds = exp * 1000;

        return Date.now() >= expirationDatetimeInSeconds;
     catch 
        return true;
    
;

不需要,但你也可以

import 'jest';
import jwt from 'jsonwebtoken';

import  isTokenExpired  from 'path-to-isTokenExpired/isTokenExpired';

describe('isTokenExpired', () => 
    it('should return true if jwt token expired', () => 
        const currentTimeInSecondsMinusThirtySeconds = Math.floor(Date.now() / 1000) - 30;
        const expiredToken = jwt.sign( foo: 'bar', exp: currentTimeInSecondsMinusThirtySeconds , 'shhhhh');

        expect(isTokenExpired(expiredToken)).toEqual(true);
    );

    it('should return false if jwt token not expired', () => 
        const currentTimeInSecondsPlusThirtySeconds = Math.floor(Date.now() / 1000) + 30;
        const notExpiredToken = jwt.sign( foo: 'bar', exp: currentTimeInSecondsPlusThirtySeconds , 'shhhhh');

        expect(isTokenExpired(notExpiredToken)).toEqual(false);
    );

    it('should return true if jwt token invalid', () => 
        expect(isTokenExpired('invalidtoken')).toEqual(true);
    );
);

【讨论】:

【参考方案5】:

我认为import * as jwt from 'jsonwebtoken'; 应该可以按预期工作。

【讨论】:

【参考方案6】:

jwt.verify 和 jwt.decode 的返回类型为'string | object'

在您的情况下,您有一些 Typescript 没有的关于返回类型的附加信息。所以你可以像这样添加它:

const token = jwt.decode(tokenBase64) as exp: number
const tokenExpirationDate = token.exp

当然,您也可以在对象中添加任何其他值。

虽然假设exp 存在是合理的,但其他键可能不存在。确保您正在解码的令牌实际上包含它们或将其添加为可选值:(exp: number; random?: string)

【讨论】:

【参考方案7】:
import * as jwt from 'jsonwebtoken'

const  authorization  = ctx.req.headers
const token = authorization.replace('Bearer ', '')
const decoded = jwt.verify(token, 'APP_SECRET')
const userId = (decoded as any).userId

当然你可以输入decoded,而不是any

【讨论】:

是的,这在所有其他选项中都有效【参考方案8】:

我发现自己为此创建了一个助手(基于类的解决方案 - 当然可以用作单独的功能):

import  JwtPayload, verify  from "jsonwebtoken";

export class BaseController 
  // ...
  static decodeJWT = <T extends  [key: string]: any >(token: string) => 
    return verify(token, process.env.JWT_ACCESS_TOKEN!) as JwtPayload & T; 
    // this typing allows us to keep both our encoded data and JWT original properties
  ;

用于以下控制器:

import  BaseController  from "./BaseController";

export class UserController extends BaseController 
  static getUser = async (
    // ...
  ) => 
    // get token
    // username may or may not be here - safer to check before use
    const payload = this.decodeJWT< username?: string >(token); 
    // no error here, we can extract all properties defined by us and original JWT props
    const  username, exp  = payload;
    // do stuff...
  ;

【讨论】:

以上是关于如何使用打字稿通过`jsonwebtoken`获取令牌到期的主要内容,如果未能解决你的问题,请参考以下文章

在 useState 的调度中使用未声明的字段时如何获取打字稿错误

如何获取带有变量的graphql查询标签的打字稿定义?

如何在angular6中使用打字稿获取当前年份

如何使用打字稿在angular2中获取设备显示的高度和宽度?

如何在猫鼬(打字稿)中获取模型的_id

在角度/打字稿中将类创建为可迭代