溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在python中利用jwt實現一個用戶認證功能

發布時間:2021-01-20 14:33:33 來源:億速云 閱讀:323 作者:Leah 欄目:開發技術

這篇文章給大家介紹怎么在python中利用jwt實現一個用戶認證功能,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

jwt的作用

json web token,一般用于用戶認證就是做用戶登錄的(前后端分離/微信小程序/app開發)

怎么在python中利用jwt實現一個用戶認證功能

基于傳統的token認證

用戶登錄,服務端返回token,并將token保存在服務端,
以后用戶再來訪問時,需要攜帶token,服務端獲取token后,再去數據庫中獲取token進行校驗

jwt

用戶登錄,服務端給用戶返回一個token(服務端不保存)
以后用戶再來訪問,需要攜帶token,服務端獲取token后,再做token的校驗----進行算法校驗

優勢:相較于傳統的token相比,它無需在服務端保存token

jwt的實現原理

第一步,用戶提交用戶名和密碼給服務器,如果登錄成功,使用jwt創建一個token,并給用戶返回.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

注意:jwt生成的token是由三段字符串組成,并且用.連接起來的

第一段字符串,HEADER,內部包含了算法/token類型,

json轉換成字符串,然后做一個base64url加密(base64加密;+_),加密再加替換

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

第二段字符串,PAYLOAD,自定義的值

讓json轉換成字符串,然后做一個base64url加密(base64加密;+_),加密再加替換

{
 "sub": "1234567890",
 "name": "John Doe",
 "iat": 1516239022 # 前兩個隨便寫,最后一個是超時時間
}

第三段字符串:他會將第一段加密之后的值,和第二段加密之后的值通過.拼接起來

第一步:第1,2部分的密文拼接起來

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

第二步:對前兩部分密文進行HS256加密 + 加鹽
第三步:對HS256加密后的密文再做base64url加密

以后用戶再來訪問的時候,需要攜帶token,后端需要對token進行校驗

獲取token

第一步: 對token進行切割,通過點切割成三部分

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

第二步: 對第二段進行 base64url 解密,并獲取payload信息,檢測token是否超時了?

{
 "sub": "1234567890",
 "name": "John Doe",
 "iat": 1516239022 # 前兩個隨便寫,最后一個是超時時間
}

第三步 :把第1,2段拼接,再次執行HS256加密

第一步:第1,2部分的密文拼接起來

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

第二步:對前兩部分密文進行HS256加密 + 加鹽

密文 = base64解密(SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c)
如果密文相等,表示token未被修改過(認證通過)

jwt的引用

pip install pyjwt
pyjwt.encode 生成token

pyjwt.decode token解密

原理性的東西

怎么在python中利用jwt實現一個用戶認證功能

怎么在python中利用jwt實現一個用戶認證功能

基于jwt和drf實現用戶認證

1.路由

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django.conf.urls import url, include
from api import views

urlpatterns = [ url('^login/$', views.LoginView.as_view()), url('^order/$', views.OrderView.as_view()),]

views

from rest_framework.views import APIView
from rest_framework.response import Response

from utils.jwt_auth import create_token
from extensions.auth import JwtQueryParamAuthentication, JwtAuthorizationAuthentication


class LoginView(APIView):
 def post(self, request, *args, **kwargs):
 """ 用戶登錄 """
 user = request.POST.get('username')
 pwd = request.POST.get('password')

 # 檢測用戶和密碼是否正確,此處可以在數據進行校驗。
 if user == 'wupeiqi' and pwd == '123':
  # 用戶名和密碼正確,給用戶生成token并返回
  token = create_token({'username': 'wupeiqi'})
  return Response({'status': True, 'token': token})
 return Response({'status': False, 'error': '用戶名或密碼錯誤'})


class OrderView(APIView):
 # 通過url傳遞token
 authentication_classes = [JwtQueryParamAuthentication, ]

 # 通過Authorization請求頭傳遞token
 # authentication_classes = [JwtAuthorizationAuthentication, ]

 def get(self, request, *args, **kwargs):
 print(request.user, request.auth)
 return Response({'data': '訂單列表'})

 def post(self, request, *args, **kwargs):
 print(request.user, request.auth)
 return Response({'data': '添加訂單'})

 def put(self, request, *args, **kwargs):
 print(request.user, request.auth)
 return Response({'data': '修改訂單'})

 def delete(self, request, *args, **kwargs):
 print(request.user, request.auth)
 return Response({'data': '刪除訂單'})

settings

SECRET_KEY = '-(e4!74gqo8q@v-y#0cz9e7aeux4qx-pl1xw#05co4avr8r+r0'

REST_FRAMEWORK = {
 "DEFAULT_VERSIONING_CLASS": 'rest_framework.versioning.URLPathVersioning',
 "ALLOWED_VERSIONS": ['v1', "v2"] #兩個認證版本
}

extensions.auth

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
from utils.jwt_auth import parse_payload


class JwtQueryParamAuthentication(BaseAuthentication):
 """
 用戶需要在url中通過參數進行傳輸token,例如:
 http://www.pythonav.com?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzM1NTU1NzksInVzZXJuYW1lIjoid3VwZWlxaSIsInVzZXJfaWQiOjF9.xj-7qSts6Yg5Ui55-aUOHJS4KSaeLq5weXMui2IIEJU
 """

 def authenticate(self, request):
 token = request.query_params.get('token')
 payload = parse_payload(token)
 if not payload['status']:
  raise exceptions.AuthenticationFailed(payload)

 # 如果想要request.user等于用戶對象,此處可以根據payload去數據庫中獲取用戶對象。
 return (payload, token)


class JwtAuthorizationAuthentication(BaseAuthentication):
 """
 用戶需要通過請求頭的方式來進行傳輸token,例如:
 Authorization:jwt eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzM1NTU1NzksInVzZXJuYW1lIjoid3VwZWlxaSIsInVzZXJfaWQiOjF9.xj-7qSts6Yg5Ui55-aUOHJS4KSaeLq5weXMui2IIEJU
 """

 def authenticate(self, request):

 # 非登錄頁面需要校驗token
 authorization = request.META.get('HTTP_AUTHORIZATION', '')
 auth = authorization.split()
 if not auth:
  raise exceptions.AuthenticationFailed({'error': '未獲取到Authorization請求頭', 'status': False})
 if auth[0].lower() != 'jwt':
  raise exceptions.AuthenticationFailed({'error': 'Authorization請求頭中認證方式錯誤', 'status': False})

 if len(auth) == 1:
  raise exceptions.AuthenticationFailed({'error': "非法Authorization請求頭", 'status': False})
 elif len(auth) > 2:
  raise exceptions.AuthenticationFailed({'error': "非法Authorization請求頭", 'status': False})

 token = auth[1]
 result = parse_payload(token)
 if not result['status']:
  raise exceptions.AuthenticationFailed(result)

 # 如果想要request.user等于用戶對象,此處可以根據payload去數據庫中獲取用戶對象。
 return (result, token)

utils.jwt_auth

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import jwt
import datetime
from jwt import exceptions

JWT_SALT = 'iv%x6xo7l7_u9bf_u!9#g#m*)*=ej@bek5)(@u3kh*72+unjv='

def create_token(payload, timeout=20):
 """
 :param payload: 例如:{'user_id':1,'username':'wupeiqi'}用戶信息
 :param timeout: token的過期時間,默認20分鐘
 :return:
 """
 headers = {
 'typ': 'jwt',
 'alg': 'HS256'
 }
 payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)
 result = jwt.encode(payload=payload, key=JWT_SALT, algorithm="HS256", headers=headers).decode('utf-8')
 return result

def parse_payload(token):
 """
 對token進行和發行校驗并獲取payload
 :param token:
 :return:
 """
 result = {'status': False, 'data': None, 'error': None}
 try:
 verified_payload = jwt.decode(token, JWT_SALT, True)
 result['status'] = True
 result['data'] = verified_payload
 except exceptions.ExpiredSignatureError:
 result['error'] = 'token已失效'
 except jwt.DecodeError:
 result['error'] = 'token認證失敗'
 except jwt.InvalidTokenError:
 result['error'] = '非法的token'
 return result

擴展

pip3 install djangorestframework-jwt 和上面的類似不建議使用,就是加了一些配置文件,只能在drf中用,太局限l

關于怎么在python中利用jwt實現一個用戶認證功能就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女