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 ...
随机推荐
- 延时任务-基于netty时间轮算法实现
一.时间轮算法简介 为了大家能够理解下文中的代码,我们先来简单了解一下netty时间轮算法的核心原理 时间轮算法名副其实,时间轮就是一个环形的数据结构,类似于表盘,将时间轮分成多个bucket(比如: ...
- 设置 Git 用户名和邮箱
安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址.因为每一个提交都会使用这些信息,如果你不完善它们,在 GitHub 远程仓库里很有可能没有你的贡献统计. 以下操作需要你打开 Git ...
- spring使用junit单元测试
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test& ...
- java中list集合的几种去重方式
public class ListDistinctExample { public static void main(String[] args) { List<Integer> list ...
- 微软Azure配置中心 App Configuration (二):Feature Flag 功能开关特性
写在前面 Web服务开发过程中我们经常有这样的需求: 某些功能我必须我修改了配置才启用,比如新用户注册送券等: 某个功能需到特定的时间才启用,过后就失效,比如春节活动等: 某些功能,我想先对10%的用 ...
- San(COCI2017.2)题解
题意 一个人为了楼顶的金币要去跳楼,但是不能往更矮的楼上跳. 求在一个长为N的序列中总点权值和大于等于K的不下降序列数. N<=40,K<=4e10 官方题解 折半搜索的经典例子!N在20 ...
- JavaScript 设计模式及代码实现——代理模式
代理模式 1 定义 为其他对象提供一种代理以控制对这个对象的访问 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 2 应用举例 2.1 缓 ...
- C语言小游戏: 推箱子 支线(一)--1
好家伙,考完试了 回顾一下2021 回顾一下某次的作业 妙啊 所以, 做一个推箱子小游戏 1.先去4399找一下关卡灵感 就它了 2.在百度上搜几篇推箱子, 参考其中的"■ ☆"图 ...
- Linux虚拟机快捷键大全
转发请注明原作者! 图形化命令框快捷键 Ctrl-Shift-t 创建标签页 Ctrl-Shift-w 关闭标签页 Ctrl-Shift-n 创建新窗口 Ctrl-Shift-q 关闭新窗口 Ctrl ...
- js函数( 普通函数、箭头函数 ) 内部this的指向
- 普通函数 | 具名普通函数.匿名普通函数,在不作为对象的属性值的情况下,其内部的 this 总是指向代码运行环境下的全局对象 ( 例如,浏览器中的 window ). 示例: (functio ...