JWT在项目中实践小结

原创
2017/07/13 18:10
阅读数 3.5K

  JWT即JSON WEB TOKEN的缩写,轻量级的令牌认证(相比于oauth),可用于数据交换间的安全传输,同时可使用公钥/私钥的非对称算法对信息进行数字签名,如RS256算法。

  它由3部分组成:

  • Header  头信息
  • Payload  荷载信息,实际数据;一个token的第二个部分是荷载信息,它包含一些声明Claim(实体的描述,通常是一个User信息,还包括一些其他的元数据)
  • Signature  由头信息+荷载信息+密钥 组合之后进行加密得到,使用header中指定的算法将编码后的header、编码后的payload、一个secret进行加密

  3部分的所包含的内容及详细组成网上已很多,这里不再啰嗦,我们只对jwt实际使用过程的注意事项及坑做下分享,希望后来者可以更好的使用jwt。   

  【一】项目实践中需要注意一下几点:  

  1、由于palyload部分的实际数据可很容易被解出,所以在实际应用中,切记不可在其中传输敏感数据,如密码、秘钥等信息,jwt能做到的主要是防止数据被篡改。

  2、非对称算法,如RS256皆是服务于签名,即Signature部分,目的就是为了让服务器可以很明确的知道收到的数据是否合法,因此在客户端去做此jwt生成过程是不明智的,容易将密钥公之于众,这样也就失去了jwt防篡改功能。(有一点想不明白的是,如果使用非对称算法,那么公钥理论可以公开,这时候如何保证数据的合法性??我们目前使用的是HS256算法,只有一个密钥且不可公开)

  3、jwt涉及base64及加密处理,所以会使传输的数据会比裸传数据大很多,这个需要根据实际情况评估并做好平衡

 【二】 可能的使用场景:

  1、单点登录,此场景也是使用最广的一种,流程原理很简单:

  用户登录成功-》生成token返回前端并保存(cookie或localstorage)-》之后每次请求在header或body中带此token-》服务器验证此token以保证数据合法性

  以下引用jwt官网的一张图,可大概说明以上jwt过程:

    此场景应用相比于cookie直接保存登录信息,可有效防止CSRF攻击(原理可见:https://segmentfault.com/a/1190000003716037),

  CSRF (Cross Site Request Forgery),它讲的是你在一个浏览器中打开了两个标签页,其中一个页面通过窃取另一个页面的 cookie 来发送伪造的请求,因为 cookie 是随着请求自动发送到服务端的。

    2、与第三方接口的数据传输,在处理对外接口时(特别是公司之外业务)可很方便的作为一个约定,可很好的减少由于数据安全性问题所要做的沟通工作。

  但由于jwt涉及base64及加密处理,所以会使传输的数据会比裸传数据大很多,这方面大家可以根据实际情况做平衡取舍。对于公司内部的项目及对传输数据量有极高要求的更要慎重考虑用jwt方式;对于这种情况,我们目前的处理方式是模仿jwt,但使用内部约定的签名方式对数据进行数字签名,以达到目的。

【三】JWT、JWS、JWE区别(网上摘录)

  一开始很迷茫于这几个缩写的区别,应该很多人跟我有同样迷茫,特意查了下,

  1、3个的全拼:JWT(JSON Web Tokens)、JWS(JSON Web Signature)、JWE(JSON Web Encryption)

  2、关于JWT,可参考RFC7519(https://tools.ietf.org/html/rfc7519)的描述:

  JSON Web Token (JWT) 是一个间接地、URL安全的,表现为一组声明,可以在双方之间进行传输。一个JWT的声明,是指经过编码后的一个JSON对象,这个JSON对象可以是一个JSON Web     Signature(JWS)结构的荷载(payload),或者是一个JSON Web Encryption(JWE)结构的明文。允许使用声明进行数字签名,或者通过一个Message Authentication Code(MAC)进行完整性保护可选择是否加密。

  即,一组JWT声明(JSON格式的Claims)被通过JWS结构或JWE结构发送。JWS和JWE实际上是一个荷载,JWT则是一种基于荷载的实际实现。

  3、JWS,对内容进行数字化签名

  4、JWE,对内容进行加密,而不是签名,JWT声明会被加密码,因此带来了内容的保密性。JWE可以被签名并附在JWS里。这样的话就可以同时加密和签名。

  5、对于客户端,分辨JWS或JWE

  JWS的Header与JWE的Header是不同的,可以通过检查“alg”Header参数的值来区分。如果这个值表现为一个数字签名或者MAC的算法,或者是”none“,则它是一个JWS。

  如果它表现为一个 Key Encryption, Key Wrapping, Direct Key Agreement, Key Agreement with Key Wrapping, or Direct Encryption algorithm。则它是一个JWE。

  还可以通过Header里的“enc”(encryption algorithm)是否存在来判断,如果"enc"这个成员存在的话说明是JWE,否则的话就是JWS.

附,以下我整理了下开发过程用到的jwt包:

在线debuger及各种语言lib包:https://jwt.io/ 

php包:https://github.com/psecio/jwt

javascript/nodejs包:https://kjur.github.com/jsrsasign

展开阅读全文
JWt
打赏
0
41 收藏
分享
加载中
果然是小结
2017/07/21 13:36
回复
举报
goodman_fz博主

引用来自“尘风了了”的评论

确定是实践?
实践确实误导了?标题修改了下
2017/07/21 08:56
回复
举报
goodman_fz博主

引用来自“尘风了了”的评论

确定是实践?

@尘风了了 不然呢?难道要贴代码,呵呵
2017/07/20 22:27
回复
举报
确定是实践?
2017/07/20 12:08
回复
举报
goodman_fz博主

引用来自“cyper”的评论

var token = req.body.token || req.headers[‘x-access-token’];
if (token) {
jwt.verify(token, 'secret', function(err, decoded) {
if (err) {
console.error(‘JWT Verification Error’, err);
return res.status(403).send(err);
} else {
req.decoded = decoded;
return next();
}
});
} else {
res.status(403).send(‘Token not provided’);
}
}

@cyper
2017/07/16 08:16
回复
举报
厉害了
2017/07/15 18:08
回复
举报
var token = req.body.token || req.headers[‘x-access-token’];
if (token) {
jwt.verify(token, 'secret', function(err, decoded) {
if (err) {
console.error(‘JWT Verification Error’, err);
return res.status(403).send(err);
} else {
req.decoded = decoded;
return next();
}
});
} else {
res.status(403).send(‘Token not provided’);
}
}
2017/07/15 11:06
回复
举报
nodejs: npm install jsonwebtoken

登录时生成token
var User = require('./userModel');
var jwt = require('jsonwebtokens');
var newUser = function (req, res){
User.findOne({where:{ username: req.body.username }})
.then(function (user) {
if(!user){
User.create({
username: req.body.username,
password: req.body.password,
email: req.body.email
})
.then(function(user){
var myToken = jwt.sign({ user: user.id },
'secret',
{ expiresIn: 24 * 60 * 60 });
res.send(200, {'token': myToken,
'userId': user.id,
'username': user.username });
});
} else {
res.status(404).json('Username already exist!');
}
})
.catch(function (err) {
res.send('Error creating user: ', err.message);
});
};

使用时解密JWT

var authorize = function(req, res, n
2017/07/15 11:06
回复
举报
更多评论
打赏
8 评论
41 收藏
0
分享
返回顶部
顶部