乐趣区

关于jwt:jwt身份认证概述

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

退出移动版