JSON Web Tokens(JWT)

简介:

JWT 即:JSON Web Token,定义了一种紧凑的、自包含的方式,用于在网络应用环境间以 JSON 对象安全地传输信息。

JWT 是一个开放的行业标准 RFC 7519。JWT 传输的信息可以被验证和信任,因为它经过了数字签名。

JWT 一般被用来在身份提供者和服务提供者间传递被认证用户的身份信息,以便于从资源服务器获取资源,也可以增加一些额外的业务逻辑所需的声明信息。

JWT 常用于代替 Session,用于识别用户身份。传统上使用 Session 机制区别用户身份有两个缺点:一是占用服务器的存储资源,二是在集群部署下设计会非常复杂。JWT 完全可以解决 Session 方案存在的问题。

一,安装

$ npm install jsonwebtoken

二,用法

jwt.sign(payload, secretOrPrivateKey, [options, callback])

(异步)如果提供了回调,则使用err或JWT调用回调。

(同步)以字符串形式返回JsonWebToken

有效载荷可以是表示有效JSON的对象文字、缓冲区或字符串。

请注意,只有当有效载荷是对象文字时,才会设置exp或任何其他声明。未检查缓冲区或字符串有效负载的JSON有效性。

如果有效负载不是缓冲区或字符串,则会使用JSON.stringify将其强制转换为字符串。

secretOrPrivateKey是一个字符串(utf-8编码)、缓冲区、对象或KeyObject,包含HMAC算法的秘密或RSA和ECDSA的PEM编码私钥。如果是带有密码短语的私钥,则可以使用对象{key,passphrase}(基于加密文档),在这种情况下,请确保您通过了算法选项。使用RSA算法进行签名时,最小模数长度为2048,除非allowInsecureKeySizes选项设置为true。低于此大小的私钥将被拒绝,并出现错误。

选项

算法(默认值:HS256)

expiresIn:以秒或描述时间跨度vercel/ms的字符串表示。

例如:60,“2天”,“10小时”,“7天”。数值被解释为秒计数。如果使用字符串,请确保提供时间单位(天、小时等),否则默认使用毫秒单位(“120”等于“120ms”)。

notBefore:以秒或描述时间跨度vercel/ms的字符串表示。

例如:60,“2天”,“10小时”,“7天”。数值被解释为秒计数。如果使用字符串,请确保提供时间单位(天、小时等),否则默认使用毫秒单位(“120”等于“120ms”)。

audience; issuer;jwtid; subject;noTimestamp;header;keyid
mutatePayload:如果为true,sign函数将直接修改payload对象。如果在对有效负载应用声明之后但在将其编码为令牌之前需要对其进行原始引用,则这一点非常有用。

allowInsecureKeySizes:如果为true,则允许模数低于2048的私钥用于RSA

allowInvalidAsymmetricKeyTypes:如果为true,则允许与指定算法不匹配的非对称密钥。此选项仅用于向后兼容,应避免使用。

expiresIn、notBefore、audience、subject、issuer没有默认值。这些声明也可以分别用exp、nbf、aud、sub和iss直接提供在有效载荷中,但不能同时包含在这两个位置。

请记住,exp、nbf和iat是NumericDate,请参阅相关的Token Expiration(exp声明)

标头可以通过options.header对象进行自定义。

默认情况下,生成的jwt将包括iat(在发布)声明,除非未指定时间戳。如果在有效载荷中插入iat,则将使用它而不是实际的时间戳来计算其他事情,如在options.exiresIn中给定时间跨度的exp。

默认同步签名(HMAC SHA256)   

var jwt = require('jsonwebtoken');
var token = jwt.sign({ foo: 'bar' }, 'shhhhh');

异步签名

jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' }, function(err, token) {
  console.log(token);
});

回溯30秒

var older_token=jwt.sign({foo:'bar',iat:Math.floor(Date.now()/1000)-30},'shhh')

代币到期(exp索赔)

JWT的标准定义了过期的exp索赔。过期时间表示为NumericDate:

JSON数值,表示从1970-01-01T00:00:00Z UTC到指定的UTC日期/时间的秒数,忽略闰秒。这相当于IEEE Std 1003.1,2013版[POSIX.1]定义的“自大纪元以来的秒数”,其中每天精确地计算86400秒,而不是可以表示非整数值。有关日期/时间,特别是UTC的详细信息,请参阅RFC 3339[RFC3339]。

这意味着exp字段应该包含自epoch以来的秒数。

正在签署过期1小时的令牌:

jwt.sign({
  exp: Math.floor(Date.now() / 1000) + (60 * 60),
  data: 'foobar'
}, 'secret');

使用此库生成类似令牌的另一种方法是:

jwt.sign({
  data: 'foobar'
}, 'secret', { expiresIn: 60 * 60 });

//甚至更好:

jwt.sign({
  data: 'foobar'
}, 'secret', { expiresIn: '1h' });
    jwt.verify(token, secretOrPublicKey, [options, callback])

(异步)如果提供了回调,函数将异步执行。如果签名有效并且可选的过期、访问群体或颁发者有效,则使用解码的有效负载调用回调。如果没有,它将被调用并返回错误。
(同步)如果没有提供回调,函数将同步执行。如果签名有效并且可选的过期、访问群体或颁发者有效,则返回解码的有效负载。否则,它将抛出错误。
警告:当令牌来自不受信任的来源(例如用户输入或外部请求)时,应将返回的解码有效载荷视为任何其他用户输入;请确保进行消毒,并且只使用预期的属性
token是JsonWebToken字符串
secretOrPublicKey是一个字符串(utf-8编码)、缓冲区或KeyObject,包含HMAC算法的秘密,或RSA和ECDSA的PEM编码公钥。如果jwt.verify是异步调用的,secretOrPublicKey可以是一个应该获取密钥或公钥的函数。请参阅下面的详细示例
如本评论所述,还有其他库需要base64编码的机密(使用base64编码随机字节),如果是这种情况,您可以传递Buffer.from(secret,'base64'),通过这样做,机密将使用base64解码,令牌验证将使用原始随机字节。
选项
algorithms:包含允许的算法名称的字符串列表。例如,[“HS256”,“HS384”]。
如果未指定,将根据提供的密钥类型使用默认值
secret-['HS256','HS384','HS512']
rsa-['RS256','RS384','RS512']
ec-【'ES256’、'ES384’、'ES 512’】
默认值-['RS256'、'RS384'、'RSM12']
audience:如果您想检查audience(aud),请在此处提供一个值。可以对照字符串、正则表达式或字符串和/或正则表达式的列表来检查受众。
例如:“urn:foo”,/un:f[o]{2}/,[/urn:f[o]{2}-,“urn:bar”]
complete:返回一个具有解码的{payload,header,signature}的对象,而不是仅返回有效载荷的常规内容。
isser(可选):iss字段的有效值的字符串或字符串数组。
jwtid(可选):如果要检查JWT ID(jti),请在此处提供一个字符串值。
ignoreExpiration:如果为true,则不验证令牌的过期时间。
ignoreNotBefore。。。
subject:如果要检查subject,请在此处提供值
clockTolerance:检查nbf和exp声明时允许的秒数,用于处理不同服务器之间的小时钟差异
maxAge:允许令牌仍然有效的最大年龄。它以秒或描述时间跨度vercel/ms的字符串表示。
例如:1000,“2天”,“10小时”,“7天”。数值被解释为秒计数。如果使用字符串,请确保提供时间单位(天、小时等),否则默认使用毫秒单位(“120”等于“120ms”)。
clockTimestamp:应用作所有必要比较的当前时间的时间(以秒为单位)。
nonce:如果要检查nonce声明,请在此处提供一个字符串值。它用于ID令牌的Open ID。(Open ID实施说明)
allowInvalidAsymmetricKeyTypes:如果为true,则允许与指定算法不匹配的非对称密钥。此选项仅用于向后兼容,应避免使用。

// verify a token symmetric - synchronous
var decoded = jwt.verify(token, 'shhhhh');
console.log(decoded.foo) // bar
// verify a token symmetric
jwt.verify(token, 'shhhhh', function(err, decoded) {
  console.log(decoded.foo) // bar
});
// invalid token - synchronous
try {
  var decoded = jwt.verify(token, 'wrong-secret');
} catch(err) {
  // err
}
// invalid token
jwt.verify(token, 'wrong-secret', function(err, decoded) {
  // err
  // decoded undefined
});
// verify a token asymmetric
var cert = fs.readFileSync('public.pem');  // get public key
jwt.verify(token, cert, function(err, decoded) {
  console.log(decoded.foo) // bar
});
// verify audience
var cert = fs.readFileSync('public.pem');  // get public key
jwt.verify(token, cert, { audience: 'urn:foo' }, function(err, decoded) {
// if audience mismatch, err == invalid audience
});
// verify issuer
var cert = fs.readFileSync('public.pem');  // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer' }, function(err, decoded) {
  // if issuer mismatch, err == invalid issuer
});
// verify jwt id
var cert = fs.readFileSync('public.pem');  // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid' }, function(err, decoded) {
  // if jwt id mismatch, err == invalid jwt id
});
// verify subject
var cert = fs.readFileSync('public.pem');  // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid', subject: 'subject' }, function(err, decoded) {
  // if subject mismatch, err == invalid subject
});
// alg mismatch
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) {
  // if token alg != RS256,  err == invalid signature
});
// Verify using getKey callback
// Example uses https://github.com/auth0/node-jwks-rsa as a way to fetch the keys.
var jwksClient = require('jwks-rsa');
var client = jwksClient({
  jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json'
});
function getKey(header, callback){
  client.getSigningKey(header.kid, function(err, key) {
    var signingKey = key.publicKey || key.rsaPublicKey;
    callback(null, signingKey);
  });
}
jwt.verify(token, getKey, options, function(err, decoded) {
  console.log(decoded.foo) // bar
});

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JSON Web Tokens (JWTs)在前端的应用非常广泛。JWT是一种轻量级的安全传输机制,用于在不同系统之间安全地传输信息。它是一种基于JSON的开放标准(RFC 7519),用于在各个实体之间以可靠和安全的方式传输信息。 在前端应用中,JWTs通常用于身份验证和授权。以下是JWT前端应用中的常见应用方式: 1. 用户身份验证:当用户登录时,服务器会生成一个包含用户信息和其他相关数据的JWT,并将其返回给客户端。客户端可以将JWT存储在本地(通常使用浏览器的本地存储,如localStorage或sessionStorage),并在后续请求中将其作为身份验证凭证发送给服务器。服务器可以验证JWT的签名,并从中提取用户信息,以确认用户的身份。 2. 跨域身份验证:当前端应用需要与多个不同域的后端服务进行交互时,可以使用JWT作为跨域身份验证解决方案。客户端在登录后获取JWT,并将其发送到其他后端服务作为身份验证凭证。后端服务可以验证JWT的签名并提取其中的信息,以确认用户的身份。 3. 授权和权限管理:JWT可以包含有关用户角色和权限的信息。在前端应用中,可以使用JWT来控制用户对不同功能和资源的访问权限。前端应用可以解析JWT并根据其中的角色和权限信息来决定显示哪些功能或资源。 4. 单点登录(Single Sign-On,SSO):JWT也可以用于实现单点登录功能。当用户在一个应用中登录后,该应用会生成一个JWT,并将其发送给身份提供者(如身份验证服务器)。其他需要用户身份验证的应用可以通过验证JWT来确认用户的身份,而无需用户再次登录。 总结起来,JWT前端应用中可以用于用户身份验证、授权和权限管理,以及实现跨域身份验证和单点登录等功能。使用JWT可以减少服务器端的状态管理,提高系统的可扩展性和性能。然而,在使用JWT时需要注意安全性,例如使用HTTPS来传输JWT,避免将敏感信息存储在JWT中,并定期更新JWT的密钥等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值