JWT全称JSON Web Token

利用流程

  1. 客户端应用用户名和明码申请登录,服务端收到申请
  2. 验证用户名和明码正确后,后端通过JWT机制,将用户数据作为JWTPayload,同时在后面拼接上一个JWT Header之后进行Base64编码,并进行签名,生成一个token,格局为header.payload.signature,返回给客户端
  3. 客户端后续的每次申请都须要携带token,携带在HTTP Header Authorization
  4. 后端拿到客户端传递的token后,进行解密验证身份,验证其有效性,查看签名是否正确,是否过期,最初解析出JWT Token中的用户信息

长处

  • 无状态,token机制在服务端不须要存储session信息,因为token本身蕴含了所有登录用户的信息,所以能够加重服务端压力
  • 分布式敌对,因为session须要固定保留在一个中央,如果保留在本机,分布式系统中认证会生效,如果采纳redis等对立保留session,零碎复杂性会减少
  • 反对跨域拜访,跨域后不会存在信息失落问题
  • CDN敌对,能够通过内容散发网络申请服务端的所有材料
  • 挪动端敌对,当客户端是非浏览器平台时,cookie是不被反对的,此时采纳token认证形式会简略很多
  • 无需思考CSRF(Cross Site Request Forgery跨站点申请伪造),token是开发者为了防备csrf而特地设计的令牌,浏览器不会主动增加到headers里,攻击者也无法访问用户的token,所以攻击者提交的表单无奈通过服务器认证,也就无奈造成攻打

    CSRF简述

    1. 在一个浏览器中关上了两个标签页,其中一个页面通过窃取另一个页面的 cookie 来发送伪造的申请,因为cookie 是随着浏览器申请主动发送到服务端的,这个是CSRF攻打胜利的外围起因
    2. session认证实质须要依赖Cookie,如果cookie被截获,用户很容易受到跨站申请伪造攻打
    3. CSRF无奈间接窃取到用户的Cookie,header,仅仅是冒用Cookie

毛病

  • 不可控,因为JWT无状态,想要在JWT 有效期内废除一个JWT或者更改它的权限的话,并不会立刻失效,通常须要等到有效期过后才能够,如果要防止这个问题,须要把JWT存入redis等缓存,JWT生效的时候就删除这个JWT,每次验证的时候查问一下JWT在不在redis,然而这样就减少了老本和零碎复杂度
  • token续签不不便,JWT自身payload参数当中携带exp参数示意过期工夫,payload批改之后签名也须要批改,所以须要从新生成一个JWT
  • JWT令牌个别会比拟长,如果是性能极度敏感的话须要在意这一点

组成

JWT生成的Token由三局部组成:header.payload.signature,艰深地说,JWT的实质是一个字符串,将用户信息保留到一个Json字符串中,而后进行编码后失去一个JWT token,并且这个JWT token带有签名信息,接管后能够校验是否被篡改,所以能够用于在各方之间平安地将信息作为Json对象传输

  • header

    • alg:指定signature采纳的加密算法,默认是HS256(HMAC SHA256),对称加密(加密和解密的密钥雷同)
    • typ:固定值,通常是JWT
    • 通常值是{"alg": "HS256", "typ": "JWT"}, 通过base64Url算法进行编码之后进行拼接
  • payload

    • 用户idname
    • 默认携带iat,令牌签发工夫(工夫戳)
    • exp设置令牌过期工夫
    • 参数个别模式如下,通过base64Url算法进行编码与header进行拼接,默认状况下JWT是未加密的,因为只是采纳base64算法,拿到JWT字符串后能够转换回本来的JSON数据,任何人都能够解读其内容,因而不要构建隐衷信息字段,比方用户的明码肯定不能保留到JWT中,JWT只是适宜在网络中传输一些非敏感的信息,要传递一些敏感数据的话须要应用一些AES或者其余类型的算法,尽量加上一些salt进行加密payload

      {  "sub": "1234567890",  "name": "Helen",  "admin": true}
  • signature

    • 设置一个secretKey,通过将前两个后果合并后进行HS256算法,signature = HS256(base64Url(header)+'.'+base64Url(payload),secretKey)
    • secreKey肯定不能裸露,因为能够颁发token,也能够解密

跨域资源共享

是一种基于 HTTP头的机制,该机制次要是为了防止跨站脚本攻打而存在

理论网站开发过程当中须要从A网站拜访到另外一个网站B,就须要通过容许服务器标示除了它本人以外的其余源(域、协定或端口),使得浏览器容许这些源拜访加载本人的资源,服务器须要返回一个HTTP Header Access-Control-Allow-Origin: * 表明,该资源能够被任意外源拜访,这样浏览器才会失常加载返回的数据

然而当携带cookie进行拜访的时候就不能返回一个Header头示意容许被任意外源拜访

  • 服务器不能Access-Control-Allow-Origin 的值设为通配符“*”,而应将其设置为特定的域,如:Access-Control-Allow-Origin: https://example.com,如果值被设置为*,申请会失败,如歌设置为具体的域申请胜利
  • 服务器不能Access-Control-Allow-Headers 的值设为通配符“*”,而应将其设置为标头名称的列表,如:Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
  • 服务器不能Access-Control-Allow-Methods 的值设为通配符“*”,而应将其设置为特定申请办法名称的列表,如:Access-Control-Allow-Methods: POST, GET

详情参考Mozilla对跨域资源共享的定义

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

python实现

依赖我的项目pyjwt

https://github.com/jpadilla/pyjwt

装置

$ pip install pyjwt

应用

>>> import jwt>>> encoded = jwt.encode({"some": "payload"}, "secret", algorithm="HS256")>>> print(encoded)eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg>>> jwt.decode(encoded, "secret", algorithms=["HS256"]){'some': 'payload'}

参考浏览

掘金-JWTToken详解

掘金-JWT详解

Mozilla 跨源资源共享CORS