介绍

JWT协议似乎已经应用十分广泛,JSON Web Token——一种基于token的json格式web认证方法。基本的原理是,第一次认证通过用户名密码,服务端签发一个json格式的token。后续客户端的请求都携带这个token,服务端仅需要解析这个token,来判别客户端的身份和合法性。JWT协议仅仅规定了这个协议的格式,主要分为三部分:

1.header头部:

声明类型,这里是jwt

声明加密的算法 通常直接使用 HMAC SHA256,再将其进行base64编码

{

'typ': 'JWT',

'alg': 'HS256'

}

2 payload载荷:

payload是放置实际有效使用信息的地方。JWT定义了几种内容,包括:

标准中注册的声明,如签发者,接收者,有效时间(exp),时间戳(iat,issued at)等;为官方建议但非必须

{

'user_id': 2342,

'user_role': root,

'iat': 1577255177

}

payload中的内容是自由的,按照自己开发的需要加入。

3 signature

存储了序列化的secreate key和salt key。这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

JWT实现

这里使用python模块itsdangerous,这个模块能做很多编码工作,其中一个是实现JWS的token序列。

genTokenSeq这个函数用于生成token。其中使用的是TimedJSONWebSignatureSerializer进行序列的生成,这里secret_key密钥、salt值是随机uuid,当然也可以自定义。expires_in是超时时间间隔,这个间隔以秒记,可以直接在这里设置

  1. from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
  2. import time
  3. def genTokenSeq(name, passwd, address, expires=300):
  4. '''
  5. 加密数据为jwt字符串
  6. :param name: 用户名
  7. :param passwd: 用户密码
  8. :param address: 服务器地址
  9. :param expires: 过期时间,默认5分钟,单位:秒
  10. :return: 返回字节流字符串
  11. salt:随机字符串,默认不可变,更改需要与服务器沟通
  12. secret_key:秘钥,默认不可变,更改需要与服务器沟通
  13. '''
  14. s = Serializer(
  15. salt='16fcf475-5180-4916-83c1-5ff79616eaa9',
  16. secret_key='4180da82-0c83-4d66-ab14-e2793573ecaa',
  17. expires_in=expires
  18. )
  19. timestamp = time.time()
  20. json_str = {
  21. 'user_name': name,
  22. 'user_passwd': passwd,
  23. 'user_address': address,
  24. 'timeout': expires,
  25. 'iat': timestamp
  26. }
  27. return s.dumps(json_str)

使用这个Serializer可以帮我们处理好header、signature的问题。我们只需要用s.dumps将payload的内容写进来。

生成的token是这样的 eyJleHAiOjE1NzM1NDkyOTgsImFsZyI6IkhTNTEyIiwiaWF0IjoxNTczNTQ4OTk4fQ.eyJ1c2VyX2FkZHJlc3MiOjEyMCwidGltZW91dCI6MzAwLCJpYXQiOjE1NzM1NDg5OTguODI2NjY4LCJ1c2VyX3Bhc3N3ZCI6Im0iLCJ1c2VyX25hbWUiOiJ4eCJ9.ixTUKxwB6TW8K2dQMBYb6hfZpIejEv45nPL5AfVSI8A91Ec76BroXgPTaAEPfxSER5PnAghWDkaCOhcqsMRMKA

这个是解码:

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

from itsdangerous import SignatureExpired, BadSignature, BadData

  1. def tokenAuth(token):
  2. '''
  3. 解码jwt数据
  4. :param token: jwt字符串
  5. :return: 返回解密后的数据
  6. '''
  7. s = Serializer(
  8. secret_key='4180da82-0c83-4d66-ab14-e2793573ecaa',
  9. salt='16fcf475-5180-4916-83c1-5ff79616eaa9')
  10. try:
  11. data = s.loads(token)
  12. except SignatureExpired:
  13. msg = 'token expired'
  14. return [None, msg]
  15. except BadSignature as e:
  16. encoded_payload = e.payload
  17. if encoded_payload is not None:
  18. try:
  19. s.load_payload(encoded_payload)
  20. except BadData:
  21. # the token is tampered.
  22. msg = 'token tampered'
  23. return [None, msg]
  24. msg = 'badSignature of token'
  25. return [None, msg]
  26. except:
  27. msg = 'wrong token with unknown reason'
  28. return [None, msg]
  29. if ('user_name' not in data) or ('user_passwd' not in data) or ('user_address' not in data):
  30. msg = 'illegal payload inside'
  31. return [None, msg]
  32. msg = 'user(' + data['user_name'] + ') logged in by token.'
  33. user_name = data['user_name']
  34. user_passwd = data['user_passwd']
  35. user_address = data['user_address']
  36. return [user_name, user_passwd, user_address, msg]

解析需要使用到同样的serializer,配置一样的secret key和salt,使用loads方法来解析token。itsdangerous提供了各种异常处理类,用起来也很方便:

如果是SignatureExpired,则可以直接返回过期;

如果是BadSignature,则代表了所有其他签名错误的情况,于是又分为:

能读取到payload:那么这个消息是一个内容被篡改、消息体加密过程正确的消息,secret key和salt很可能泄露了;

不能读取到payload: 消息体直接被篡改,secret key和salt应该仍然安全。

检查和判定的机制如下:

1.使用加密的类,再用来解密(用上之前的密钥和盐值),得到结果存入data;

2.如果捕获到SignatureExpired异常,则代表根据token中的expired设置,token已经超时失效,返回‘token expired’;

3.如果是其他BadSignature异常,又要分为:

3.1 如果payload还完整,则解析payload,如果捕获BadData异常,则代表token已经被篡改,返回‘token tampered’;

3.2 如果payload不完整,直接返回‘badSignature of token’;

4.如果以上异常都不对,那只能返回未知异常‘wrong token with unknown reason’;

5.最后,如果data能正常解析,则将payload中的数据取出来,验证payload中是否有合法信息,如果数据不合法,则返回‘illegal payload inside’。一旦出现这种情况,则代表密钥和盐值泄露的可能性很大。

使用python实现后台系统的JWT认证的更多相关文章

  1. 使用python实现后台系统的JWT认证(转)

    今天的文章介绍一种适用于restful+json的API认证方法,这个方法是基于jwt,并且加入了一些从oauth2.0借鉴的改良. 1. 常见的几种实现认证的方法 首先要明白,认证和鉴权是不同的.认 ...

  2. python实现后台系统的JWT认证

    介绍一种适用于restful+json的API认证方法,这个方法是基于jwt,并且加入了一些从oauth2.0借鉴的改良. 1. 常见的几种实现认证的方法 首先要明白,认证和鉴权是不同的.认证是判定用 ...

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

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

  4. Django(65)jwt认证原理

    前言 带着问题学习是最有目的性的,我们先提出以下几个问题,看看通过这篇博客的讲解,能解决问题吗? 什么是JWT? 为什么要用JWT?它有什么优势? JWT的认证流程是怎样的? JWT的工作原理? 我们 ...

  5. sau交流学习社区--songEagle开发系列:Vue.js + Koa.js项目中使用JWT认证

    一.前言 JWT(JSON Web Token),是为了在网络环境间传递声明而执行的一种基于JSON的开放标准(RFC 7519). JWT不是一个新鲜的东西,网上相关的介绍已经非常多了.不是很了解的 ...

  6. drf框架中jwt认证,以及自定义jwt认证

    0909自我总结 drf框架中jwt 一.模块的安装 官方:http://getblimp.github.io/django-rest-framework-jwt/ 他是个第三方的开源项目 安装:pi ...

  7. .Net Core 认证系统之Cookie认证源码解析

    接着上文.Net Core 认证系统源码解析,Cookie认证算是常用的认证模式,但是目前主流都是前后端分离,有点鸡肋但是,不考虑移动端的站点或者纯管理后台网站可以使用这种认证方式.注意:基于浏览器且 ...

  8. 玩转Django2.0---Django笔记建站基础八(admin后台系统)

    第八章 admin后台系统 admin后台系统也成为网站后台管理系统,主要用于对网站前台的信息进行管理,如文字.图片.影音和其他日常使用文件的发布.更新.删除等操作,也包括功能信息的统计和管理,如用户 ...

  9. 频率类组件-认证规图分析-JWT认证-drf-jwt插件

    频率类源码 # 1)APIView的dispath方法中的 self.initial(request, *args, **kwargs) 点进去 # 2)self.check_throttles(re ...

随机推荐

  1. CodeForces - 1228D (暴力+思维+乱搞)

    题意 https://vjudge.net/problem/CodeForces-1228D 有一个n个顶点m条边的无向图,在一对顶点中最多有一条边. 设v1,v2是两个不相交的非空子集,当满足以下条 ...

  2. 无序数组中用 快速排序的分治思想 寻找第k大元素

    #include <stdio.h> int *ga; int galen; void print_a(){ ; i < galen; i++){ printf("%d & ...

  3. C语言异常处理

    异常的概念-程序在运行过程中可能产生异常-异常(Exception)与Bug的区别 异常是程序运行时可预料的执行分支 Bug是程序中的错误,是不被预期的运行方式 异常(Exception)和Bug的对 ...

  4. input 控件常用属性

  5. day58_9_24多对多建表手动,form组件(判断类型),cookies和session

    一.多对多建表关系之手动添加. 1.全自动 像之前讲过的一样,我们可以通过manytomanyField的字段来建立多对多关系: class Book(models.Model): title = m ...

  6. Appium自动化WebView中元素的操作

    在App开发过程中,很容易用到第三方的WebView控件,这个属于移动端混合型App.在我们做自动化测试的过程中,就要对这种情况进行处理,最通用的办法就是先将appium切换到webview模式然后按 ...

  7. 剑指Offer-17.树的子结构(C++/Java)

    题目: 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 分析: 注意这道题是判断B是不是A的子结构,而不是子树,这一点要注意下,且空树不是任意一个树的子结构 ...

  8. 剑指Offer-5.用两个栈实现队列(C++/Java)

    题目: 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 分析: 栈的特点是先进后出,队列的特点则是先进先出. 题目要求我们用两个栈来实现一个队列,栈和队列都有入栈 ...

  9. 【PL/SQL】设置F8自动运行

  10. 洛谷P4015 运输问题 网络流24题

    看了下SPFA题解,一个一个太麻烦了,另一个写的很不清楚,而且注释都变成了"????"不知道怎么过的,于是自己来一发SPFA算法. Part 1.题意 M 个仓库,卖给 N 个商店 ...