如何使用打字稿通过`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 的调度中使用未声明的字段时如何获取打字稿错误