JSON Web Token认证介绍
  • 简称JWT认证,一般用于用户认证
  • JWT是一种相当新的标准,可用于基于token的身份验证
  • 与内置的TokenAuthentication方案不同,JWT不需要使用数据库来验证令牌
  • 优势:相较于传统的token,无需再服务端保存
基于传统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实现原理及流程代码示例

 
 
用户登录成功之后,服务端使用jwt创建一个token,并给用户返回,不在服务端存储
token由Header、Payload、Signature三部分组成,这三部分之间以小数点连接
# 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进行校验
# 校验流程
第一步:获取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'})
基于jwt和drf实现认证示例
# 自定义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认证的更多相关文章

  1. JWT(Json Web Token)认证

    目录 JWT(Json Web Token) JWT的数据结构 JWT的用法 JWT验证流程

  2. 一分钟简单了解 JSON Web Token

    JSON Web Token(JWT)是一个开放的标准(RFC 7519),它定义了一个紧凑且自包含的方式,用于在各方之间作为 JSON 对象安全地传输信息.由于此信息是经过数字签名的,因此可以被验证 ...

  3. [认证授权] 2.OAuth2(续) & JSON Web Token

    0. RFC6749还有哪些可以完善的? 0.1. 撤销Token 在上篇[认证授权] 1.OAuth2授权中介绍到了OAuth2可以帮我们解决第三方Client访问受保护资源的问题,但是只提供了如何 ...

  4. [认证授权] 2.OAuth2授权(续) & JWT(JSON Web Token)

    1 RFC6749还有哪些可以完善的? 1.1 撤销Token 在上篇[认证授权] 1.OAuth2授权中介绍到了OAuth2可以帮我们解决第三方Client访问受保护资源的问题,但是只提供了如何获得 ...

  5. webapp用户身份认证方案 JSON WEB TOKEN 实现

    webapp用户身份认证方案 JSON WEB TOKEN 实现Deme示例,Java版 本项目依赖于下面jar包: nimbus-jose-jwt-4.13.1.jar (一款开源的成熟的JSON ...

  6. 把旧系统迁移到.Net Core 2.0 日记 (18) --JWT 认证(Json Web Token)

    我们最常用的认证系统是Cookie认证,通常用一般需要人工登录的系统,用户访问授权范围的url时,会自动Redirect到Account/Login,登录后把认证结果存在cookie里. 系统只要找到 ...

  7. Laravel 5 中使用 JWT(Json Web Token) 实现基于API的用户认证

    在JavaScript前端技术大行其道的今天,我们通常只需在后台构建API提供给前端调用,并且后端仅仅设计为给前端移动App调用.用户认证是Web应用的重要组成部分,基于API的用户认证有两个最佳解决 ...

  8. JWT(Json web token)认证详解

    JWT(Json web token)认证详解 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该to ...

  9. 理解JWT(JSON Web Token)认证及python实践

    原文:https://segmentfault.com/a/1190000010312468?utm_source=tag-newest 几种常用的认证机制 HTTP Basic Auth HTTP ...

随机推荐

  1. DolphinScheduler 荣获 2021 中国开源云联盟优秀开源项目奖!

    点击上方 蓝字关注我们 好消息,中国开源云联盟(China Open Source Cloud League,简称"COSCL")于近日公布 2021 杰出开源贡献者.优秀开源项目 ...

  2. JavaScript的入门

    书写的三种方式 1. 书写在script标签里面(一般会用到的) 2.书写在js文件里面(推荐)定义一个js文件(xxx.js) 3. 书写对应的事件属性里面(比较少用) 初体验 1. 目前js的代码 ...

  3. feign远程调用出错

    如果你传递的参数,比较复杂时,默认会采用POST的请求方式. 传递单个参数时,推荐使用@PathVariable,如果传递的单个参数比较多,这里也可以采用@RequestParam,Feign接口中不 ...

  4. SpringBoot多重属性文件配置方案笔记

    SpringBoot多重属性文件配置方案笔记 需要重写PropertyPlaceholderConfigurer 同时要忽略DataSourceAutoConfiguration @SpringBoo ...

  5. Openstack Neutron : 安全

    目录 - iptable:起源 - tables - chains - rules - 方向 - Security group 安全组: - Firewall 防火墙: - 更高的安全 - 无处安放的 ...

  6. Cat Theme

    将博客皮肤设置为: SimpleMemory 插入CSS代码 #EntryTag{margin-top:20px;font-size:9pt;color:gray}.topicListFooter{t ...

  7. 干货分享|使用 Istio 实现灰度发布

    Kubernetes 作为基础平台,提供了强大的容器编排能力.但是在其上部署业务和服务治理上,仍然会面对一些复杂性和局限性.在服务治理上,已经有许多成熟的 ServiceMesh 框架用于扩充其能力, ...

  8. 数论进阶 

    数论进阶 扩展欧几里得算法 裴蜀定理(Bézout's identity) \(1\) :对于任意整数 \(a\),\(b\) ,存在一对整数 \(x\) ,\(y\) ,满足 \(ax+by=GCD ...

  9. gitlab备份和恢复

    备份 生产环境下,备份是必需的.需要备份的文件有:配置文件和数据文件. 备份配置文件 配置文件包含密码等敏感信息,不要和数据文件放在一起. sh -c 'umask 0077; tar -cf $(d ...

  10. 【golang】json数据解析 - 嵌套json解析

    @ 目录 1. 通过结构体映射解析 2. 嵌套json解析-map 1. 通过结构体映射解析 原数据结构 解析 // 结构体 type contractJson struct { Data []tra ...