python-jwt用户认证食用教学的实现方法


Posted in Python onJanuary 19, 2021

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

djangorestframework-jwt 本质是调用pyjwt实现的

使用场景两端开发,app,小程序开发!

到此这篇关于python-jwt用户认证食用教学的文章就介绍到这了,更多相关python-jwt认证内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python获取任意xml节点值的方法
May 05 Python
在Python的Django框架下使用django-tagging的教程
May 30 Python
一键搞定python连接mysql驱动有关问题(windows版本)
Apr 23 Python
python制作爬虫爬取京东商品评论教程
Dec 16 Python
Django模板变量如何传递给外部js调用的方法小结
Jul 24 Python
详解python中Numpy的属性与创建矩阵
Sep 10 Python
python多个模块py文件的数据共享实例
Jan 11 Python
python爬虫selenium和phantomJs使用方法解析
Aug 08 Python
python中seaborn包常用图形使用详解
Nov 25 Python
Python实现括号匹配方法详解
Feb 10 Python
python相对企业语言优势在哪
Jun 12 Python
Keras-多输入多输出实例(多任务)
Jun 22 Python
使用Python爬虫爬取小红书完完整整的全过程
Jan 19 #Python
python 自动识别并连接串口的实现
Jan 19 #Python
python爬取抖音视频的实例分析
Jan 19 #Python
python中的插入排序的简单用法
Jan 19 #Python
Python实现淘宝秒杀功能的示例代码
Jan 19 #Python
Python爬虫后获取重定向url的两种方法
Jan 19 #Python
详解Python+Selenium+ChromeDriver的配置和问题解决
Jan 19 #Python
You might like
使用php+xslt在windows平台上
2006/10/09 PHP
优化PHP代码技巧的小结
2013/06/02 PHP
php 注册时输入信息验证器的实现详解
2013/07/05 PHP
php源码 fsockopen获取网页内容实例详解
2016/09/24 PHP
php+mysql实现简单登录注册修改密码网页
2016/11/30 PHP
PHP实现常用排序算法的方法
2020/02/05 PHP
IE6-IE9不支持table.innerHTML的解决方法分享
2012/09/14 Javascript
Jquery增加鼠标中间功能mousewheel的实例代码
2013/09/05 Javascript
jquery div拖动效果示例代码
2013/12/08 Javascript
javascript计算当月剩余天数(天数计算器)示例代码
2014/01/09 Javascript
jQuery实现的向下图文信息滚动效果
2015/05/03 Javascript
AngularJs  Using $location详解及示例代码
2016/09/02 Javascript
轻松掌握JavaScript状态模式
2016/09/07 Javascript
Vue.js绑定HTML class数组语法错误的原因分析
2016/10/19 Javascript
Angular 4依赖注入学习教程之简介(一)
2017/06/04 Javascript
js简易版购物车功能
2017/06/17 Javascript
防止页面url缓存中ajax中post请求的处理方法
2017/10/10 Javascript
React Native 图片查看组件的方法
2018/03/01 Javascript
详解webpack 入门与解析
2018/04/09 Javascript
JS算法题之查找数字在数组中的索引位置
2019/05/15 Javascript
vue中使用带隐藏文本信息的图片、图片水印的方法
2020/04/24 Javascript
详解Vue 的异常处理机制
2020/11/30 Vue.js
[01:08:09]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#1Liquid VS Alliance第二局
2016/03/02 DOTA
Python中的Matplotlib模块入门教程
2015/04/15 Python
详解Python设计模式编程中观察者模式与策略模式的运用
2016/03/02 Python
Python处理JSON数据并生成条形图
2016/08/05 Python
独特的python循环语句
2016/11/20 Python
python中numpy包使用教程之数组和相关操作详解
2017/07/30 Python
python编程实现12306的一个小爬虫实例
2017/12/27 Python
Python 脚本的三种执行方式小结
2019/12/21 Python
解析Python 偏函数用法全方位实现
2020/06/26 Python
weblogic面试题
2016/03/07 面试题
办公室前台的岗位职责
2013/12/20 职场文书
公司员工检讨书
2014/02/08 职场文书
综合素质评价思想道德自我评价
2015/03/09 职场文书
python 如何用terminal输入参数
2021/05/25 Python