json web token

由来

  • Cookie+Session的方式,在用户登录通过验证后,服务端将 数据加密后 通过在响应头(Header)保存到客户端浏览器的Cookie(包含sid或token)中,同时服务器保留相对应的Session(文件或DB)。用户之后发起的请求(Request)都会携带Cookie信息,服 务端需要根据Cookie寻回对应的Session,从而完成验证,确认这是之前登陆过的用户。
  • API应该被设计成无状态的(Stateless)。这意味着没有登陆,注销的方法,也没有sessions,API的设计者同样也不能依赖Cookie,因为不能保证这些request是由浏览器所发出的

JWT介绍

  • 分为三段,通过解码可以得到:
// 1. Headers
// 包括类别(typ)、加密算法(alg);
{
  "alg": "HS256",
  "typ": "JWT"
}
// 2. Claims
// 包括需要传递的用户信息;
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
// 3. Signature
// 根据alg算法与私有秘钥进行加密得到的签名字串;
// 这一段是最重要的敏感信息,只能在服务端解密;
HMACSHA256(  
    base64UrlEncode(header) + "." +
    base64UrlEncode(payload),
    SECREATE_KEY
)

在使用过程中,服务端通过用户登录验证之后,将Header+Claim信息加密后得到第三段签名,然后将三段签名合并后返回给客户端。客户端获取到token后,应该在每次向服务器请求数据时附带这个token,然后服务端验证token。

  • 因此JWT是用来取代服务端的Session而非客户端Cookie的方案.对于客户端本地存储,不同的选择更多是出于安全性的考虑

  • 客户端在与服务器第一次通信时,通过一些可靠信息(用户名、密码)和服务器交换取token,这个token作为客服端再次请求的权限钥匙。Token通常比密码更加长而且复杂。JWTs通常会长达150个字符。一旦获得了token,在每次调用API的时候都要附加上它。把token想象成一个安全的护照。你在一个安全的前台验证你的身份(通过你的用户名和密码),如果你成功验证了自己,你就可以取得这个。当你走进大楼的时候(试图从调用API获取资源),你会被要求验证你的护照,而不是在前台重新验证。

client

  • client 头部值部分使用Bearer Authorization: Bearer
  • .set('Authorization', 'Bearer ' + token)

encoded

  • https://github.com/auth0/node-jsonwebtoken
jwt.sign(payload, secretOrPrivateKey, options, [callback]);

payload Claims,即传递的用户信息,could be an object literal, buffer or string.if not,it will be coerced into a string using JSON.stringify.

secretOrPrivateKey is a string or buffer containing either the secret for HMAC algorithms, or the PEM encoded private key for RSA and ECDSA.字符串,或着fs.readFileSync读取的证书

options:

  • algorithm (default: HS256) 加密算法
  • expiresIn: expressed in seconds or an string describing a time span rauchg/ms. Eg: 60, "2 days", "10h", "7d" 有效期/分钟
  • audience
  • subject
  • issuer
  • noTimestamp
  • headers

Example

// sign with default (HMAC SHA256)
var jwt = require('jsonwebtoken');
var token = jwt.sign({ foo: 'bar' }, 'shhhhh');

// sign with RSA SHA256
var cert = fs.readFileSync('private.key');  // get private key
var token = jwt.sign({ foo: 'bar' }, cert, { algorithm: 'RS256'});

decoded

  • https://github.com/auth0/express-jwt
var jwt = require('express-jwt');

app.get('/protected',
  jwt({secret: 'shhhhhhared-secret'}),
  function(req, res) {
    if (!req.user.admin) return res.sendStatus(401);
    res.sendStatus(200);            
  });

you can make some paths unprotected as follows:

//设置路由/token 不验证
app.use(jwt({ secret: 'shhhhhhared-secret'}).unless({path: ['/token']}));

By default, the decoded token is attached to req.user but can be configured with the requestProperty option.
默认解密后的token Claim内容加到req.user

//将解密后的token加到req.auth
jwt({ secret: publicKey, requestProperty: 'auth' });

安全性

  • XSS 主要原因是对用户输入信息不加过滤,导致用户 (被误导)恶意输入的Js代码在访问该网页时被执行,而Js可以读取当前网站域名下保存的Cookie信息.对用户输入的所有信息进行过滤即可,CDN服务也有可能引入不安全的Js脚本
  • CSRF,跨站请求伪造 主要利用Cookie是按照域名存储,同时访问某域名时浏览器会自动携带该域名所保存的Cookie信息这一特征.如果执意要将JWT存储在Cookie中,服务端则需要额外验证请求来源.将JWT保存在localStorage中,即将JWT放入Request Header中的Authorization位。

你可能感兴趣的:(json web token)