Description
What is a JSON Web Token?
没事就读读: What is a JSON Web Token?
JWT规范: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html
JWT分三部分 header.payload.signature
header: {typ: ‘JWT’, alg: ‘HS256’}
payload: {userId: 2, admin: true}
signature: secret(header+payload)
其中header和payload是给浏览器用的, 仅是base64 encoded, (所以不要保存敏感信息)
最后的signature是给server用的, 是用服务端secret加密过的header+payload信息.
header和payload可以直接在jwt.io这个网站上显示出来, 如下图:
JWT的传输方式
一共有三种, 分别是http header, http body 和 http url(query parameter)
1. Authorization Request Header Field
先了解一下Authorization的格式
W3C HTTP1.0规范中最早引入了如下风格的Authorization:
Authorization: <type> <credentials>
这里有解释为什么要这么定义, 简而言之, server端可能同时支持多种方式的authorization type.
如果type为Bearer那么server端有可能是实现了OAuth2(Bearer, 翻译: 持有者.)
但是这个Bearer含义最终是由你的server决定, 这里的JWT按照业内的通用做法放在Bearer后面完全可行.
GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM
2. Form-Encoded Body Parameter
POST /resource HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
access_token=mF_9.B5f-4.1JqM
3. URI Query Parameter
GET /resource?access_token=mF_9.B5f-4.1JqM HTTP/1.1
Host: server.example.com
4. 而server端响应token的格式如下:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"mF_9.B5f-4.1JqM",
"token_type":"Bearer",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
}
node jwt Tutorial 1 (仅做参考)
Make an API with Node.JS, MongoDB, and JWT Authentication
$ mkdir api-jwt && cd $_
$ npm init -y
$ npm i -S express body-parser mongoose mongoose-paginate kerberos cors morgan bcryptjs moment jwt-simple
这篇的作者写的代码真是漂亮, 知识点:
- 如何强制使用https (以及为什么jwt要配合https来使用)
- Mongoose分页
- 分离受保护和不受保护的routes.
- app/routes/controllers代码分层
- 如何用curl来测试api.
// 4. Force https in production
if (app.get('env') === 'production') {
app.use(function(req, res, next) {
var protocol = req.get('x-forwarded-proto');
protocol == 'https' ? next() : res.redirect('https://' + req.hostname + req.url);
});
}
node jwt Tutorial 2 (用得最多)
Simple Authentication in Node/Express using JWT (JSON Web Tokens)
这篇只通过两段代码演示了如何使用jwt. 我直接拷贝过来吧..
npm install jsonwebtokens
服务端生成JWT
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, next) {
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 in Action
最终我选择了"jsonwebtoken": "^7.4.1",