一、JWT 简介

jwt(JSON Web Tokens),是一种开发的行业标准 RFC 7519 ,用于安全的表示双方之间的声明。目前,jwt广泛应用在系统的用户认证方面,特别是现在前后端分离项目。

1.1 Jwt认证流程

  1. 前端用户填写好用户名和密码,点击登录
  2. 后端对提交的用户名和密码进行校验,校验通过则发送token给前端
  3. 前端将token保存在cookie中,并在每一次请求时都将cookie一并发送给后端
  4. 后端对用户发送过来的token进行校验,并通过token识别是哪个用户。

1.2 session & Token 区别

  • session

    在django中,如果使用session进行认证,会在django_session表中存储用户登录记录,随着用户增加,数据库中的记录也会越来越多,增加了服务器压力

  • token

    传统token

    ​ 用户登录成功后,服务端生成一个随机token给用户,并且在服务端(数据库或缓存)中保存一份token,以后用户再来访问时需携带token,服务端接收到token之后,去数据库或缓存中进行校验token的是否超时、是否合法。

    jwt 形式

    ​ 用户登录成功后,服务端通过jwt生成一个随机token给用户(服务端无需保留token),以后用户再来访问时需携带token,服务端 接收到token之后,通过jwt对token进行校验是否超时、是否合法。

1.3 JWT 格式

jwt是一段由.(点)组成的三段式密文

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  • 第一段称为头部(header)

    头部存储了两部分信息,分别是类别和加密算法。加密算法通常使用sha256(这里指整体加密时采用的算法),将头部进行base64url编码得到一段内容

    # 密文
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9# 解密
    {"alg": "HS256","typ": "JWT"
    }
    
  • 第二段称为payload(载荷)

    payload 里面包含用户有部分数据,比如用户id和用户名等。第二段内容也是通过base64url进行加密,所以内容中不能包含敏感数据

    # 密文
    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ# 解密
    {"sub": "1234567890","name": "John Doe","iat": 1516239022
    }
    
  • 第三段为签名(signature)

    把前两段的base64url密文通过.拼接起来,并加入秘钥,然后对其(两段密文和盐)进行HS256加密(header中定义的类别),再然后对整体密文进行base64url加密,最终得到token的第三段。

    base64url(HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),your-256-bit-secret (秘钥加盐))
    )
    

二、PyJWT 使用

2.1 简单实用

  • 安装

    pip install pyjwt
    

在django系统中使用pyjwt来实现jwt认证。

>>> import jwt
>>> key = "secret"
>>> encoded = jwt.encode({"some": "payload"}, key, algorithm="HS256")
>>> print(encoded)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg
>>> jwt.decode(encoded, key, algorithms="HS256")
{'some': 'payload'}
  • payload中的特殊参数
The JWT specification defines some registered claim names and defines how they should be used. PyJWT supports these registered claim names:“exp” (Expiration Time) Claim “nbf” (Not Before Time) Claim“iss” (Issuer) Claim“aud” (Audience) Claim“iat” (Issued At) Claim
  • exp指定过期时间

    payload = {"id":result.id,"username":result.username,'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=1)  # 超时时间,其中exp是固定写法
    }
    

    在进行decode时,会对该值进行校验token是否过期

2.2 JWT实现用户token认证案例

以django为例

路由接口

urlpatterns = [path('login',views.LoginView.as_view()),   # 生成token,并返回给用户path('order',views.OrderView.as_view())        # 验证token
]

视图书写

# 登录视图类
class LoginView(APIView):def post(self,request):username = request.POST.get('username')password = request.POST.get('password')user_obj = models.UserInfo.objects.filter(username=username,password=password).first()if not user_obj:return JsonResponse({"code":"201","msg":"用户名或密码错误"})payload = {"uid":user_obj.id,"username":user_obj.username}token = jwt_auth.creata_token(payload)return JsonResponse({"code":"200","msg":"post successful","token":token,})# 订单类
class OrderView(APIView):def get(self,request):token = request.query_params.get("token")result = jwt_auth.verify_token(token)return JsonResponse(result)

token创建&认证函数

# utils/jwt_auth
import jwt
import datetime
from django.conf import settingsdef creata_token(payload,):"""生成token:param payload: 用于生成token的部分用户信息:return: 生成的token"""# 1.构造headersheaders = {'typ': 'jwt','alg': 'HS256'}# 2.构造payloadpayload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=1) # 指定过期时间为1分钟# 3.生成token并返回token = jwt.encode(payload=payload, key=settings.SECRET_KEY, algorithm="HS256")return tokendef verify_token(token):"""验证token的有效性:param token::return:"""result = {"code": "202"}try:# true 表示集成了对时间等校验verified_payload = jwt.decode(token, settings.SECRET_KEY, algorithms="HS256")print(verified_payload)result['msg'] = verified_payloadresult['code'] = 200except jwt.exceptions.ExpiredSignatureError:result['error'] = "身份信息已失效,请重新登录"except jwt.DecodeError:result['error'] = "Token认证失败"except jwt.InvalidTokenError:result['error'] = "非法token"return result

实验测试结果

  • 生成token

  • 有效期token结果

  • 过期token

三、利用DRF设置用户认证

自定义认证类

# utils/jwt_auth.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailedclass JwtGlobalAuth(BaseAuthentication):def authenticate(self, request):token = request.query_params.get("token")result = {"code": "202"}try:# true 表示集成了对时间等校验verified_payload = jwt.decode(token, settings.SECRET_KEY, algorithms="HS256")result['msg'] = verified_payloadresult['code'] = 200except jwt.exceptions.ExpiredSignatureError:result['error'] = "身份信息已失效,请重新登录"raise AuthenticationFailed(result)except jwt.DecodeError:result['error'] = "Token认证失败"raise AuthenticationFailed(result)except jwt.InvalidTokenError:result['error'] = "非法token"raise AuthenticationFailed(result)# drf 认证类可以返回三种类型值# 1.抛出异常# 2.返回一个元组return (verified_payload,token)# 3.返回None

视图中加载用户认证 - 局部认证

# api/views.py
class OrderView(APIView):authentication_classes = [jwt_auth.JwtGlobalAuth,]def get(self,request):ret = "这里是订单详情"return JsonResponse(ret,safe=False)

全局token认证

# settings.py
import api
REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.jwt_auth.JwtGlobalAuth']    # 默认认证类,全局有效
}
  • 视图类

    # api/views.pyclass LoginView(APIView):authentication_classes = []      # 解除登录时的token认证def post(self,request):username = request.POST.get('username')password = request.POST.get('password')user_obj = models.UserInfo.objects.filter(username=username,password=password).first()if not user_obj:return JsonResponse({"code":"201","msg":"用户名或密码错误"})payload = {"uid":user_obj.id,"username":user_obj.username}token = jwt_auth.creata_token(payload)return JsonResponse({"code":"200","msg":"post successful","token":token,})class OrderView(APIView):def get(self,request):ret = "这里是订单详情"return JsonResponse(ret,safe=False)
    

JWT 快速入门,并实现登录认证相关推荐

  1. Spring Boot JWT 快速入门

    本章节讨论 jwt 在 spring boot 中的应用.意在快速入门 jwt. java jdk1.8 maven 3.2+ spring boot 2.0+ JSON Web Token(JWT) ...

  2. 使用JWT实现微服务统一登录认证

    前言 在开始JWT之前,我们弄清楚什么是有状态? 有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session. 例如登 ...

  3. 菜鸟学习shiro之入门的简单登录认证和身份认证1

    最近学习了四郎,学的是天南海北,一头雾水,概念懂了,实践呐,就很是缺乏,于是跟着慕课网的视频教程敲敲代码 果然加深了理解,话不多说,直接看代码 Maven的依赖: <dependencies&g ...

  4. SpringBoot 快速集成 JWT 实现用户登录认证

    前言:当今前后端分离时代,基于Token的会话保持机制比传统的Session/Cookie机制更加方便,下面我会介绍SpringBoot快速集成JWT库java-jwt以完成用户登录认证. 一.JWT ...

  5. Shiro第四篇【Shiro与Spring整合、快速入门、Shiro过滤器、登陆认证】

    Spring与Shiro整合 导入jar包 shiro-web的jar. shiro-spring的jar shiro-code的jar 快速入门 shiro也通过filter进行拦截.filter拦 ...

  6. 基于jwt的用户登录认证

    最近在app的开发过程中,做了一个基于token的用户登录认证,使用vue+node+mongoDB进行的开发,前来总结一下. token认证流程: 1:用户输入用户名和密码,进行登录操作,发送登录信 ...

  7. jwt认证机制优势和原理_微服务统一登录认证怎么做?JWT?

    无状态登录原理 1.1.什么是有状态? 有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session. 例如登录:用户登 ...

  8. shiro+jwt登录认证anon配置无效

    shiro+jwt登录认证anon配置无效 需求:使用shiro+jwt进行登录认证,希望可以自定义一些不需要认证的接口(登录接口等),其他统统交给jwtFilter进行token认证 原来shiro ...

  9. Day241242.单点登录方案【Jwt令牌、sessionredis、CAS认证服务器】 -springsecurity-jwt-oauth2

    1.单点登录与状态共享方案 随着企业的应用规模不断增大,一个单体应用很难满足用户量增长的需求,这就需要我们将单体应用集群化部署,或者将单体应用微服务化.在这个过程中,就涉及到两个问题: 集群应用之间如 ...

最新文章

  1. Java企业实训 - 01 - Java前奏
  2. linux存储--虚拟内存详解MMU、页表(十)
  3. servlet destroy 示例_KET答题卡怎么填写?2020年KET答题卡填涂示例
  4. C/C++学习之路_七: 内存管理
  5. android发送网络请求没反应,Android无法使用HttpURLConnection发送GET请求
  6. 无限式查找-----2013年2月28日
  7. python django开发框架_Python Django 框架开发
  8. python爬取图片失败什么原因_请问下面这个python3.5下的爬虫程序有什么错误,为什么运行正常 但是不爬取图片?...
  9. 《凤凰架构》读书笔记
  10. 计算机系军训口号四句霸气,军训口号 四句 霸气
  11. 微信群控系统源码,微信云控系统源码的升级版,一部手机操作100个微信号的核心源码实现,核心技术架构
  12. el-select和el-tree组成树下拉框以及数据回显
  13. php ci 优化,CodeIgniter 性能优化
  14. 配置git的合并工具mergetool不生成.orig文件
  15. unbuntu 安装vscode
  16. @GuardedBy注解
  17. R语言进行数据分组聚合统计变换(Aggregating transforms)、计算dataframe数据的分组四分位距(IQR)
  18. centos7安装W3AF
  19. 中国城市资本流动问题探索
  20. 登录mysql报错Failed to connect to backoff 或 Failed to get D-Bus connection: Operation not permitted解决方法

热门文章

  1. 清华大学研读间助手-清华小图Android
  2. 为什么CRM管理软件在企业中如此重要
  3. Node-RED教程(十四):定制Node-REDUI
  4. 怎么把几个单独的pdf文件合并为一个pdf文件?怎么把多个pdf整合成同一个pdf?
  5. Qt中的拖拽(针对两个界面之间的拖动)
  6. [WebApi]appsettings.json 数据库连接
  7. 你不知道的JavaScript上卷-作用域和闭包
  8. 【计算机考研复习计划】数学二+英语二+政治+408相关科目的复习建议
  9. js的 算法 和 数据结构
  10. POJ 2386 dfs求连通块