JWT认证机制

1. 定义

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明通常被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也能够增长一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。html

2. 传统的Session认证

2.1 流程

session认证的流程通常以下:python

  1. 用户向服务器发送用户名和密码。web

  2. 服务器验证经过后,在当前对话(session)里面保存相关数据,好比用户角色、登陆时间等等。算法

  3. 服务器向用户返回一个 session_id,写入用户的 Cookie。django

  4. 用户随后的每一次请求,都会经过 Cookie,将 session_id 传回服务器。浏览器

  5. 服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。安全

2.2 缺点

  • session保存在服务器,当注册用户不少,会增长服务器的开销。bash

  • 用户认证以后,服务端作认证记录,若是认证的记录被保存在内存中的话,这意味着用户下次请求还必需要请求在这台服务器上,这样才能拿到受权的资源,这样在分布式的应用上,限制了负载均衡的能力。这也意味着限制了应用的扩展能力。服务器

  • session是基于cookie来进行用户识别的, cookie若是被截获,用户就会很容易受到跨站请求伪造(CSRF)的攻击。cookie

3.JWT认证

3.1 token

JWT是基于token的鉴权机制相似于http协议也是无状态的,它不须要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不须要去考虑用户在哪一台服务器登陆了,这就为应用的扩展提供了便利。

3.2 流程

  1. 用户使用用户名密码来请求服务器

  2. 服务器进行验证用户的信息

  3. 服务器经过验证发送给用户一个token

  4. 客户端存储token,并在每次请求时附送上这个token值

  5. 服务端验证token值,并返回数据

这个token必需要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS(跨来源资源共享)策略,通常咱们在服务端这么作就能够了Access-Control-Allow-Origin: *

3.3 JWT构成

第一部分咱们称它为头部(header),第二部分咱们称其为载荷(payload),第三部分是签证(signature).

官方连接jwt.io/

header

jwt的头部承载两部分信息:

  • 声明类型,这里是jwt

  • 声明加密的算法 一般直接使用 SHA256

# 头部相似以下信息:{ "alg": "HS256", "typ": "JWT"}复制代码

将头部进行base64加密(该加密是能够对称解密的),构成了第一部分.获得的加密信息是以下的一串字符串:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9复制代码
payload

载荷就是存放有效信息的地方。这些有效信息包含三个部分:

  • 标准中注册的声明

  • 公共的声明

  • 私有的声明

{  "name": "John",  "admin": true,  “email”:"xxx@gmail.com"}复制代码

该部分也是base64加密的,加密后获得下面字符串:

ewogICJuYW1lIjogIkpvaG4iLAogICJhZG1pbiI6IHRydWXvvIwKICDigJxlbWFpbOKAnToieHh4QGdtYWlsLmNvbSIKfQ复制代码
signature

JWT的第三部分是一个签证信息,这个签证信息由三部分组成:

  • header (base64加密)

  • payload (base64加密)

  • secret 密钥

这个部分须要base64加密后的headerbase64加密后的payload使用.链接组成的字符串,而后经过header中声明的加密方式进行SHA256组合加密(不可逆加密),而后就构成了jwt的第三部分。将这三部分用.链接成一个完整的字符串,构成了最终的jwt

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,因此,它就是你服务端的私钥,在任何场景都不该该流露出去。一旦客户端得知这个secret, 那就意味着客户端是能够自我签发jwt了。若是以为密钥泄露了,请及时修改。

4. 后台设置

下面介绍的是在djangorestframework基础上的jwt集成方案。首先确保djangorestframework在设置文件中应用中注册。

安装

pip install djangorestframework-jwt复制代码

配置

INSTALLED_APPS = [
    ...
    'djangorestframework',
    ...
]
# 认证
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), # JWT_EXPIRATION_DELTA 指明token的有效期
}复制代码

路由

from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    # JWT 完成登陆
    url(r'^authorizations/$', obtain_jwt_token),
]复制代码

利用djangorestframework-jwt生成的token值保存在浏览器的Storage中。