42.JSON Web Token认证
- 简称JWT认证,一般用于用户认证
- JWT是一种相当新的标准,可用于基于token的身份验证
- 与内置的TokenAuthentication方案不同,JWT不需要使用数据库来验证令牌
- 优势:相较于传统的token,无需再服务端保存
#传统的token认证
1.用户登录服务端返回token,并将token保存在服务端(缓存、db等都可以)
2.以后用户访问的时候,需要携带token,服务端获取携带token后去数据库获取token校验
#model示例
class UserInfo(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
token = models.CharField(max_length=64, null=True, blank=True)
#view示例
class LoginView(APIView):
def post(self, request, *args, **kwargs):
user = request.data.get('username')
pwd = request.data.get('password')
# 密码验证成功生成token,否则返回错误
user_object = UserInfo.objects.filter(username=user, password=pwd).first()
if not user_object:
return Response({'code': 1, 'error': '用户名或者密码错误'})
# 使用uuid的方式生成token
random_string = str(uuid.uuid4())
# 数据库保存token
user_object.token = random_string
user_object.save()
return Response({'code': 0, 'data': random_string})
class OrderView(APIView):
def get(self, request, *args, **kwargs):
# 请求的时候携带token,后端获取token
token = request.query_params.get('token')
if not token:# 没有获取到token
return Response({'code': 2, 'error': '登录成功之后才能访问'})
# 获取到的token 与数据库的token不匹配
user_object = UserInfo.objects.filter(token=token).first()
if not user_object:
return Response({'code': 3, 'error': 'token无效'})
return Response({'code': 0, 'data': 'order list'})

# jwt token 示例
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.keH6T3x1z7mmhKL1T3r9sQdAxxdzB6siemGMr_6ZOwU
#Header部分
第一段字符串:Header,内部包含算法和token类型,算法默认使用hs256,token类型是jwt
{
"alg": "HS256",
"typ": "JWT"
}
将上面JSON转换成字符串,然后做base64url加密,生成上述token第一段header字符串
# Payload部分
第二段字符串:Payload,我们自定义的值的地方,例如下方
{
"id":"123",
"name":"qi",
"xxx":"aaa",
"exp":1516239022 #超时时间,一般都要设置
}
将上面JSON转换成字符串,然后做base64url加密,生成上述token第二段Payload字符串
因为Payload部分是我们自定义的字段,可以使用base64url反解密,所以这部分不要放敏感内容
# Signature部分
第三段字符串:Signature
第一步:将第1、2部分的密文拼接起来
第二步:对钱2部分密文进行hs256加密 + 加盐
第三部:对hs256加密后的密文,在做base64url加密
# 校验流程
第一步:获取token
第二步:对token进行切割,切割成三部分
第三步:对第二段进行base64url解密并获取payload信息
获取超时时间验证是否超时
第四步:由于md5和hs256不能反解密
我们再将第一段、第二段字符串拼接进行hs256加密
第五步:将新加密的密文和第三段通过base64解密后的密文对比
如果密文相等,表示token未修改过,认证通过
'''
如果仿造jwt token,将第二段密文base64反解密,修改了过期时间之后再加密传给服务端
那么即时过期时间验证通过,和第三段密文不匹配,也验证不通过
如果把修改后的第二段和第一段通过加密生成匹配的密文去验证,但是由于第三部分不止加密,并且还加盐,所以也不会通过
'''
#安装
pip3.9 install pyjwt
#创建jwt token 流程示例
import jwt
import datetime
class LoginView(APIView):
def post(self, request, *args, **kwargs):
user = request.data.get('username')
pwd = request.data.get('password')
user_object = UserInfo.objects.filter(username=user, password=pwd).first()
if user_object:
# 加密的盐值,自定义,不能变化,不然验证的时候无法通过
salt = 'ahjgdsashjgdhjsagfdfasghfdghas'
# 构造header,加密算法除了hs256还支持其他算法,参考文档支持内容
headers = {
'typ': 'jwt',
'alg': 'HS256'
}
# 构造payload
payload = {
'user_id': user_object.id,
'username': user_object.username,
# 超时时间设置为3分钟
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=3)
}
# 生成jwt token
token = jwt.encode(payload=payload, key=salt, algorithm='HS256', headers=headers).decode('utf-8')
return Response({'code': 0, 'data': token})
else:
return Response({'code': 1, 'error': '用户名或者密码错误'})
# jwt token 校验流程示例
class getInfoLIst(APIView):
def get(self, request, *args, **kwargs):
salt = 'ahjgdsashjgdhjsagfdfasghfdghas'
# 获取token
token = request.query_params.get('token')
try:
# 从token中获取payload,进行校验,包喊过期时间、第三段密文校验
# true是校验合法性,False是不校验合法性
verified_payload = jwt.decode(token, salt, True)
return Response({'code': 0, 'data': verified_payload['user_id']})
# 如果token过期,会抛出ExpiredSignatureError异常
except jwt.exceptions.ExpiredSignatureError:
return Response({'code': 1, 'error': 'token失效'})
# 如果token认证失败,会抛出DecodeError异常
except jwt.DecodeError:
return Response({'code': 2, 'error': 'token认证失败'})
# 如果token非法,会抛出InvalidTokenError异常
except jwt.InvalidTokenError:
return Response({'code': 3, 'error': '非法的token'})
# 自定义utils-创建token
import jwt
from django.conf import settings
import datetime
def create_token(payload, timeout=3):
'''
:param payload: payload是我们自定义的部分,不同view可能制定字段不一样
所以可以其他字段外部定义好传入,在基础上添加超时时间即可
:param timeout: token超时时间,默认为3分钟,
:return:
'''
salt = settings.SECRET_KEY
headers = {
'typ': 'jwt',
'alg': 'HS256'
}
# 构造payload-给payload添加超时时间
payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)
token = jwt.encode(payload=payload, key=salt, algorithm='HS256', headers=headers).decode('utf-8')
return token
#views-创建token
# 导入创建token的方法
from jwt_demo.extensions.jwt_utils import create_token
class LoginView(APIView):
def post(self, request, *args, **kwargs):
user = request.data.get('username')
pwd = request.data.get('password')
user_object = UserInfo.objects.filter(username=user, password=pwd).first()
if user_object:
# 调用创建token的方法
token = create_token({'user_id': user_object.id})
return Response({'code': 0, 'data': token})
else:
return Response({'code': 1, 'error': '用户名或者密码错误'})
认证-创建auth.py文件
from django.conf import settings
# 认证异常的包
from rest_framework.exceptions import AuthenticationFailed
# 继承认证基类
'''
认证类中可以有三种操作
1.抛出异常,后续不再执行
2.返回一个元组,request.user,request.auth
3.返回None
'''
class JwtQueryParamsAuthentication(BaseAuthentication):
def authenticate_header(self, request):
salt = settings.SECRET_KEY
token = request.query_params.get('token')
try:
# 进行校验
payload = jwt.decode(token, salt, True)
# 抛出异常
except jwt.exceptions.ExpiredSignatureError:
raise AuthenticationFailed({'code': 1, 'error': 'token失效'})
except jwt.DecodeError:
raise AuthenticationFailed({'code': 2, 'error': 'token认证失败'})
except jwt.InvalidTokenError:
raise AuthenticationFailed({'code': 3, 'error': '非法的token'})
return (payload, token)
#view-认证
#导入自定义认证类
from jwt_demo.extensions.auth import JwtQueryParamsAuthentication
class getInfoLIst(APIView):
#指定自定义认证类 或者直接settings中配置全局
authentication_classes = [JwtQueryParamsAuthentication,]
def get(self, request, *args, **kwargs):
...
42.JSON Web Token认证的更多相关文章
- JWT(Json Web Token)认证
目录 JWT(Json Web Token) JWT的数据结构 JWT的用法 JWT验证流程
- 一分钟简单了解 JSON Web Token
JSON Web Token(JWT)是一个开放的标准(RFC 7519),它定义了一个紧凑且自包含的方式,用于在各方之间作为 JSON 对象安全地传输信息.由于此信息是经过数字签名的,因此可以被验证 ...
- [认证授权] 2.OAuth2(续) & JSON Web Token
0. RFC6749还有哪些可以完善的? 0.1. 撤销Token 在上篇[认证授权] 1.OAuth2授权中介绍到了OAuth2可以帮我们解决第三方Client访问受保护资源的问题,但是只提供了如何 ...
- [认证授权] 2.OAuth2授权(续) & JWT(JSON Web Token)
1 RFC6749还有哪些可以完善的? 1.1 撤销Token 在上篇[认证授权] 1.OAuth2授权中介绍到了OAuth2可以帮我们解决第三方Client访问受保护资源的问题,但是只提供了如何获得 ...
- webapp用户身份认证方案 JSON WEB TOKEN 实现
webapp用户身份认证方案 JSON WEB TOKEN 实现Deme示例,Java版 本项目依赖于下面jar包: nimbus-jose-jwt-4.13.1.jar (一款开源的成熟的JSON ...
- 把旧系统迁移到.Net Core 2.0 日记 (18) --JWT 认证(Json Web Token)
我们最常用的认证系统是Cookie认证,通常用一般需要人工登录的系统,用户访问授权范围的url时,会自动Redirect到Account/Login,登录后把认证结果存在cookie里. 系统只要找到 ...
- Laravel 5 中使用 JWT(Json Web Token) 实现基于API的用户认证
在JavaScript前端技术大行其道的今天,我们通常只需在后台构建API提供给前端调用,并且后端仅仅设计为给前端移动App调用.用户认证是Web应用的重要组成部分,基于API的用户认证有两个最佳解决 ...
- JWT(Json web token)认证详解
JWT(Json web token)认证详解 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该to ...
- 理解JWT(JSON Web Token)认证及python实践
原文:https://segmentfault.com/a/1190000010312468?utm_source=tag-newest 几种常用的认证机制 HTTP Basic Auth HTTP ...
随机推荐
- 《Python高手之路 第3版》这不是一本常规意义上Python的入门书!!
<Python高手之路 第3版>|免费下载地址 作者简介 · · · · · · Julien Danjou 具有12年从业经验的自由软件黑客.拥有多个开源社区的不同身份:Debian开 ...
- Luogu2343 宝石管理系统(平衡树)
平衡树维护总第K大:插入 #include <iostream> #include <cstdio> #include <cstring> #include < ...
- Luogu1880 [NOI1995]石子合并 (区间DP)
一个1A主席树的男人,沦落到褪水DP举步维艰 #include <iostream> #include <cstdio> #include <cstring> #i ...
- ceph 009 管理定义crushmap 故障域
管理和自定义crushmap 定义pg到osd的映射关系 通过crush算法使三副本映射到理想的主机或者机架 更改故障域提高可靠性 pg到osd映射由crush实现 下载时需要将对象从osd搜索到,组 ...
- Excelize 发布 2.6.0 版本,功能强大的 Excel 文档基础库
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准.可以使用它来读取.写入由 Microsoft Exc ...
- 【c语言简单算法】1-阶乘
求n的阶乘 算法要求 从键盘输入一个数,求出这个数的阶乘 代码实现 #include main() { double result=1; size_t n; scanf("%d", ...
- ABAQUS和UG许可证冲突问题的解决方案
前段时间重新安装了ABAQUS,更新到了2020版本后,发现NX UG怎么突然打不开了,搜索一下,发现是两个许可证有冲突.找了很多解决方案,主要归纳为以下两种: 方法一:Lmtools修改法 先说结论 ...
- 如何修改SAO用户密码
KingbaseES SAO 用户是专门用于审计管理的用户,用户配置审计策略需要使用该用户.在initdb 完成后,SAO 用户的默认密码保存在参数 sysaudit.audit_table_pas ...
- python 数据挖掘模块学习
项目中用到的模块 API # 模块: import pandas as pd import numpy as np from scipy.optimize import curve_fit numpy ...
- 二进制redis集群部署
二进制redis集群部署 〇.前言 无聊想学罢了 准备环境: 三台centos7 1C1GB即可 三个路相连的地址 主机 IP 节点-角色-实例(端口) redis1 172.16.106.128 M ...