Understand JWT in one article

1. Introduction to JWT

JWT (Json Web Token) is an open standard (RFC 7519) that defines a concise, self-contained method for securely transmitting information in the form of JSON objects between communicating parties. JWT can be signed using HMAC algorithm or RSA public key key pair. It has two characteristics:

Compact

It can be sent through URL, POST parameters or in HTTP header, because the amount of data is small and the transmission speed is fast

Self-contained

The load contains the information required by all users, avoiding multiple queries to the database

2. JWT composition

JWT is a string of three pieces of information. These three pieces of information text are .linked together to form a Jwt string. like this:

The first part is called the header, the second part is called the payload (payload, similar to what is carried on an airplane), and the third part is the signature.

header

The header of jwt carries two parts of information:

  • Declaration type, here is jwt
  • It is stated that the encryption algorithm usually directly uses HMAC SHA256

The complete header looks like the following JSON:

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

Then the header is encrypted with base64.b64encode() (the encryption can be symmetrically decrypted), forming the first part.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Base64 encryption and decryption in python

import base64
str1 = 'admin'
str2 = str1.encode()
b1 = base64.b64encode(str2) #数据越多,加密后的字符串越长
b2 = base64.b64decode(b1) #admin
各个语言中都有base64加密解密的功能,所以我们jwt为了安全,需要配合第三段加密

payload

The payload is where the valid information is stored. This name seems to specifically refer to the goods carried on the plane, and the effective information can store the following three parts of information.

  • Declaration registered in the standard
  • Public statement
  • Private statement

Declaration registered in the standard (recommended but not mandatory):

  • iss : jwt issuer

  • sub : the user targeted by jwt

  • aud : the party receiving the jwt

  • exp : the expiration time of jwt, this expiration time must be greater than the issuance time

  • nbf : Define the time before the jwt is unavailable.

  • iat : jwt issuance time

  • jti : The unique identity of jwt, which is mainly used as a one-time token to avoid replay attacks.

    The above are the 7 official fields specified by JWT for selection

Public statement : Any information can be added to a public statement, generally adding user-related information or other necessary information required by the business. However, it is not recommended to add sensitive information because this part can be decrypted on the client.

Private statement : A private statement is a statement jointly defined by providers and consumers. It is generally not recommended to store sensitive information, because base64 is symmetrically decrypted, which means that this part of information can be classified as plaintext information.

Define a payload, data in json format:

{
  "sub": "1234567890",
  "exp": "3422335555", #时间戳形式
  "name": "John Doe",
  "admin": true
}

Then encrypt it with base64.b64encode() to get the second part of the JWT.

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

signature

The third part of JWT is a visa information, this visa information consists of three parts:

  • header (after base64)
  • payload (after base64)
  • secret key

This part requires the base64-encrypted header and base64-encrypted payload to use .the string formed by the connection, and then perform the salt secretcombination encryption through the encryption method declared in the header , and then constitute the third part of jwt.

// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString, 'secret'); //xxxx //  TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

.Connect these three parts into a complete string to form the final jwt:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

Note: The secret is stored on the server side, and the signing of jwt is also on the server side. The secret is used for the issuance of jwt and the verification of jwt. Therefore, it is the private key of your server and should not be exposed in any scene. Once the client knows this secret, it means that the client can self-sign jwt.

jwt的优点:
1. 实现分布式的单点登陆非常方便
2. 数据实际保存在客户端,所以我们可以分担都武器的存储压力
3. JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。

jwt的缺点:
1. 数据保存在了客户端,我们服务端只认jwt,不识别客户端。
2. jwt可以设置过期时间,但是因为数据保存在了客户端,所以对于过期时间不好调整。#secret_key轻易不要改,一改所有客户端都要重新登录

Authentication flow chart:

First, the front-end sends its user name and password to the back-end interface through a web form. This process is generally an HTTP POST request. The recommended way is to use SSL encrypted transmission (https protocol) to prevent sensitive information from being sniffed.

After the backend successfully checks the user name and password, it uses the user's id and other information as the JWT Payload (payload), which is respectively Base64 encoded and spliced ​​with the header to form a JWT. The resulting JWT is a string similar to lll.zzz.xxx.

The back end returns the JWT string as the result of successful login to the front end. The front-end can save the returned results in localStorage or sessionStorage, and the front-end can delete the saved JWT when logging out.

The front end puts the JWT into the Authorization bit in the HTTP Header every time it requests. (Solve XSS and XSRF issues)

    5.后端检查是否存在,如存在验证JWT的有效性。例如,检查签名是否正确;检查Token是否过期;检查Token的接收方是否是自己(可选)。

Three. Use

1. Installation:

pip install djangorestframework-jwt -i https://mirrors.aliyun.com/pypi/simple/

2. Configuration
Configure https://github.com/jpadilla/django-rest-framework-jwt
in the settings file:

REST_FRAMEWORK = {
    
    
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}
import datetime
JWT_AUTH = {
    
    
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), 
}
  • JWT_EXPIRATION_DELTA indicates the validity period of the token

Generate jwt manually

The documentation for the Django REST framework JWT extension provides a way to manually issue JWT

from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)

In sub-app routing urls.py

from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    path(r'login/', obtain_jwt_token),
]

In the main route, import the route file of the current sub-application

urlpatterns = [
		...
    path('user/', include("users.urls")),
    # include 的值必须是 模块名.urls 格式,字符串中间只能出现一个圆点
]

Front end save jwt

We can save the JWT in a cookie or in the browser's local storage, we save it in the browser's local storage

The browser's local storage provides two types, sessionStorage and localStorage, which belong to the window object:

  • sessionStorage is invalid when the browser is closed
  • localStorage is valid for a long time

Instructions

sessionStorage.变量名 = 变量值   // 保存数据
sessionStorage.setItem("变量名","变量值") // 保存数据
sessionStorage.变量名  // 读取数据
sessionStorage.getItem("变量名") // 读取数据
sessionStorage.removeItem("变量名") // 清除单个数据
sessionStorage.clear()  // 清除所有sessionStorage保存的数据

localStorage.变量名 = 变量值   // 保存数据
localStorage.setItem("变量名","变量值") // 保存数据
localStorage.变量名  // 读取数据
localStorage.getItem("变量名") // 读取数据
localStorage.removeItem("变量名") // 清除单个数据
localStorage.clear()  // 清除所有sessionStorage保存的数据

Guess you like

Origin blog.csdn.net/qq_45066628/article/details/109409284