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 ...
随机推荐
- Mybatis完整版详解
一.简介 1.什么是MyBatis MyBatis 是一款优秀的持久层框架 它支持自定义 SQL.存储过程以及高级映射. MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作 ...
- java学习第一天.day02
整数类型常量 整数类型的常量JVM默认使用 int 类型来存储 小数类型类型 小数类型的常量JVM默认使用 double 类型来存储 . ASCII表 A在码表的顺序是65,a在码表的顺序是97
- EMAS Serverless到底有多便利?
EMAS Serverless 简介 EMAS Serverless 是阿里云提供的基于Serverless技术的一站式后端开发平台,为开发者提供高可用.弹性伸缩的云开发服务,包含云函数.云数据库.云 ...
- Web 前端实战:雷达图
前言 在Canvas 线性图形(五):多边形实现了绘制多边形的函数.本篇文章将记录如何绘制雷达图.最终实现的效果是这样的: 绘制雷达图 雷达图里外层 如动图中所示,雷达图从里到外一共有 6 层,所以, ...
- 记一次有意思的 SQL 实现 → 分组后取每组的第一条记录
开心一刻 今天,朋友气冲冲的走到我面前 朋友:我不是谈了个女朋友,谈了三个月嘛,昨天我偷看她手机,你猜她给我备注什么 我:备注什么? 朋友:舔狗 2 号! 我一听,气就上来了,说道:走,找她去,这婆娘 ...
- Go 语言入门 1-管道的特性及实现原理
入坑 go 也快一年了,从今天开始会定期分享一下 Go 语言学习过程中的一些基础知识. go 语言中的管道, 主要是用于协程之间的通信, 比 UNIX 的管道更加轻量和易用. 我们先看一下管道的数据结 ...
- KingbaseES V8R6集群部署案例之---Windows环境配置主备流复制(同一主机)
案例说明: 目前KingbaseES V8R6的Windows版本不支持数据库sys_rman的物理备份,可以考虑通过建立主备流复制实现数据库的异机物理备份.本案例详细介绍了,在Windows环境下建 ...
- HDFS 分布式环境搭建
HDFS 分布式环境搭建 作者:Grey 原文地址: 博客园:HDFS 分布式环境搭建 CSDN:HDFS 分布式环境搭建 准备四个Linux实例 每个实例对应的 host 和 ip 地址如下 nod ...
- java script 日常学习 正则表达式
<!DOCTYPE html><html><head> <title>函数的运用</title> <meta charset=&quo ...
- 使用 Win2D 实现融合效果
1. 融合效果 在 CSS 中有一种实现融合效果的技巧,使用模糊滤镜(blur)叠加对比度滤镜(contrast)使两个接近的元素看上去"粘"在一起,如下图所示: 博客园的 Cho ...