JSON Web Token令牌(JWT)的使用(一)JWT的原理、配置、创建使用

@[TOC](JSON Web Token令牌(JWT)的使用(一)JWT的原理、配置、创建使用)

详情请查看jwt官网

为何需要用jwt

jwt是通过客户端保存数据,而服务器根本不保存会话数据,每个请求都被发送回服务器。

jwt是什么

JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

应用在什么环境

  • Authorization (授权) :
    这是使用JWT的最常见场景。一旦用户登录,后续每个请求都将包含JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用的JWT的一个特性,因为它的开销很小,并且可以轻松地跨域使用。
  • Information Exchange (信息交换) : 对于安全的在各方之间传输信息而言,JSON Web
    Tokens无疑是一种很好的方式。因为JWTs可以被签名,例如,用公钥/私钥对,你可以确定发送人就是它们所说的那个人。另外,由于签名是使用头和有效负载计算的,您还可以验证内容没有被篡改。

JWT的数据结构

典型的,一个JWT看起来如下图。
改对象为一个很长的字符串,字符之间通过"."分隔符分为三个子串。注意JWT对象为一个长字串,各字串之间也没有换行符,此处为了演示需要,我们特意分行并用不同颜色表示了。每一个子串表示了一个功能块,总共有以下三个部分:

JWT的三个部分如下。JWT头、有效载荷和签名,将它们写成一行如下。
JSON Web Token令牌(JWT)的使用(一)JWT的原理、配置、创建使用_第1张图片

  • Header
  • Payload
  • Signature

因此,一个典型的JWT看起来是这个样子的:

xxxxx.yyyyy.zzzzz

接下来,具体看一下每一部分:

Header头部

header典型的由两部分组成:token的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等)。

例如:

{
  "alg": "HS256",
  "typ": "JWT"
}

然后,用Base64对这个JSON编码就得到JWT的第一部分

Payload有效负载

JWT的第二部分是payload,它包含声明(要求)。声明是关于实体(通常是用户)和其他数据的声明。声明有三种类型: registered, public 和 private。

Registered claims : 这里有一组预定义的声明,它们不是强制的,但是推荐。比如:iss (issuer), exp (expiration time), sub (subject), aud (audience)等。
Public claims : 可以随意定义。
Private claims : 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明。
下面是一个例子:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

对payload进行Base64编码就得到JWT的第二部分

注意,不要在JWT的payload或header中放置敏感信息,除非它们是加密的。

Signature签名

为了得到签名部分,你必须有编码过的header、编码过的payload、一个秘钥,签名算法是header中指定的那个,然对它们签名即可。

例如:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

签名是用于验证消息在传递过程中有没有被更改,并且,对于使用私钥签名的token,它还可以验证JWT的发送方是否为它所称的发送方。

官网示例图

在这里插入图片描述

jwt的流程

JSON Web Token令牌(JWT)的使用(一)JWT的原理、配置、创建使用_第2张图片

如何在django使用jwt

需要先进行配置,具体可以看:https://github.com/GetBlimp/django-rest-framework-jwt/blob/master/docs/index.md

下面是实例,在创建完用户之后创建jwt令牌并发送给前端

settings.py配置jwt

import datetime
REST_FRAMEWORK = {
    # 异常处理指定
    'EXCEPTION_HANDLER': 'shanghuishop.utils.exceptions.code_exp_handler',
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',  # session认证
        'rest_framework.authentication.BasicAuthentication'  # 基本认证
    )
}
# 设置过期时间
JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=60*60*24),
}

在serializers.py使用

要先写一个token然后加进fields里面:

token = serializers.CharField(label='JWT令牌-TOKEN', read_only=True)

内容是写在系列化器的create方法里,已经生成了user的

from rest_framework_jwt.settings import api_settings
	
def create(self, validated_data):
	# 把不需要存进去的删掉
	 del validated_data['password_confirm']
	 del validated_data['phone_msg']
	 # 第一种方式进行加密
	 # user = super().create(validated_data)
	 # user.set_password(validated_data['password'])
	 # user.save()
	 # 第二种方式:用drf自带的用户方法来注册用户密码会进行加密
	 user = Users.objects.create_user(**validated_data)
	 # 手动创建用户令牌
	 jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
	 jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
	 payload = jwt_payload_handler(user)
	 print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@2')
	 print(payload)
	 token = jwt_encode_handler(payload)
	 print(token)
	 # 给user动态添加属性
	 user.token = token
	 return user

在前端ajax请求成功函数里可以取值

返回的值是object类型

success: function (rec_data) {
                console.log(rec_data);
                var token = rec_data['token'];
                console.log(token);
                // 浏览器关闭则无效
                // sessionStorage.token = token;
                // 长期有效, 一般用这个,先做清除操作,避免之前遗留问题
                localStorage.clear();  
                localStorage.token = token;
                // 获取token
                alert(localStorage.token)
            }

获取完之后需要保存,两种做法:一个是sessionStrorage,一个是loaclStrorage一般用后一个

你可能感兴趣的:(Django)