专栏首页python语言学习JWT(json-web-token) 详解及应用

JWT(json-web-token) 详解及应用

JWT(json-web-token) 详解及应用

什么是JWT

Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),

该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明一般被用来在

身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加

一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

一般用于用户认证(前后端分离/微信小程序/app开发).

基于token的认证和传统的Session认证的区别

传统的session认证

http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,

那么下一次请求时,用户还要再一次进行用户认证才行,因为根据http协议,我们并不能知道是哪个用户发送的请求,

所以为了让我们的应用能识别是哪个用户发出的,我们只能在服务器存储一份用户登陆的信息,

这份登陆信息会在响应时传递给服务器,告诉其保存为cookie,以便下次请求时发送给我们的应用,

这样我们的英哟个就能识别请求来自哪个用户了,这就是传统的基于sessino认证,但是这种基于session

的认证使应用本身很难得扩展,随着不用客户端的增加,独立的服务器已无法承载更多的用户,

而这个时候基于session认证应用的问题就会暴露出来.

session:每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以便用户下次请求的鉴别,

通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大.扩展性:用户认证之后,

服务端做认证记录,如果认证的记录被保存在内存的话,这意味着用户下次请求还必须要请求在这台服务器上,

这样才能拿到授权的资源,这样在分布式的应用上,响应的限制了负载均衡器的能力,也意味着限制了应用的扩展性

CSRF:因为是基于cookie来进行用户识别的,cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击.

基于token的鉴权机制

基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或会话信息。

这也就意味着机遇tokent认证机制的应用不需要去考虑用户在哪一台服务器登陆了,这就为应用的扩展提供了便利.

  • 流程是这样的 用户使用用户名密码请求服务器 服务器进行验证用户信息 服务器通过验证发送给用户一个token 客户端存储token,并在每次请求时附加这个token值 服务器验证token,并返回数据 这个token必须要在每次请求时发送给服务器,它应该保存在请求头中,另外,服务器要支持CORS (跨来源资源共享)策略,一般我们在服务端这么做就可以了 Access-Control-Allow-Origin:*

传统的token认证

用户登录成功后,服务端生成一个随机token给用户,并且在服务端(数据库或缓存)中保存一份token,

以后用户再来访问时需携带token,服务端接收到token之后,去数据库或缓存中进行校验token的是否超时、是否合法。

JWT认证

用户登录,服务端给用户返回一个token(服务端不保存).

以后用户再来访问,需要携带token,服务端获取token后,再做token的校验.

优势:相较于传统的token相比,它无需在服务端保存token.

JWT实现过程

  • JWT通常由三部分组成: 头信息(header), 消息体(payload)和签名(signature)。

用户提交用户名和密码给服务端,如果登录成功,使用jwt创建一个token,并给用户返回(返回的token如下).

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

注意:jwt生成的token是由三段字符串组成,并且用.(点)连接起来.

第一段字符串,HEADER, 内部包含算法/token类型.

json转化成字符串,然后做 base64url 加密.(注意:base64url加密是先做base64加密,然后再将 - 替代 + 及 _ 替代 /)

{
  "alg": "HS256",
  "typ": "JWT"
}

这里的算法是可以改的

第二段字符串,payload,自定义值.

json转化成字符串,然后做 base64url 加密

{
  "id": "123123",
  "name": "chenggen",
  "exp": 1516239022 # 超时时间
}

字典的第一第二键值对是用户信息(可以根据需要使用用户信息,注意避免使用用户敏感信息如:密码),exp是超时时间

第三段字符串:

第一步: 第1,2部分密文拼接起来

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

第二步:对前2部分密文进行HS256加密 + 加盐

第三步:对HS256加密后的密文再做base64url加密

  • 以后用户再来访问时候,需要携带token,后端需要对token进行校验

第一步: 获取token,对token进行切割

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

第二步: 对第二段进行base64url解密,并获取payload信息,检测token是否已经超时?

{
  "id": "123123",
  "name": "chenggen",
  "exp": 1516239022 # 超时时间
}

第三步: 把第1,2端拼接,再次执行sha256加密

1: 第1,2部分密文拼接起来

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

2:对前2部分密文进行HS256加密 + 加盐

密文 = base64解密(SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c)

如果相等,表示token未被修改过.(认证通过)

JWT应用示列

# 安装 pip install pyjwt
pyjwt.encode 生成token
pyjwt.decode token解密


# jwt创建token代码
import jwt
import datetime
from jwt import exceptions
SALT = 'iv%x6xo7l7_u9bf_u!9#g#m*)*=ej@bek5)(@u3kh*72+unjv='
def create_token():
    # 构造header
    headers = {
        'typ': 'jwt',
        'alg': 'HS256'
    }
    # 构造payload
    payload = {
        'user_id': 1, # 自定义用户ID
        'username': 'gkf', # 自定义用户名
        'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=5) # 超时时间
    }
    result = jwt.encode(payload=payload, key=SALT, algorithm="HS256", headers=headers).decode('utf-8')
    return result
if __name__ == '__main__':
    token = create_token()
    print(token)
    
# jwt验证token代码
import jwt
from jwt import exceptions
SALT = 'iv%x6xo7l7_u9bf_u!9#g#m*)*=ej@bek5)(@u3kh*72+unjv='
def get_payload(token):
    """
    根据token获取payload
    :param token:
    :return:SALT
    """
    SALT = 'dsszfdfasfxz2123&*#^%&@&#*'
    try:
        # 从token中获取payload【不校验合法性】
        # unverified_payload = jwt.decode(token, None, False)
        # print(unverified_payload)
        # 从token中获取payload【校验合法性】
        verified_payload = jwt.decode(token, SALT, True)
        return verified_payload
    except exceptions.ExpiredSignatureError:
        print('token已失效')
    except jwt.DecodeError:
        print('token认证失败')
    except jwt.InvalidTokenError:
        print('非法的token')

if __name__ == '__main__':
    token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzM1NTU1NzksInVzZXJuYW1lIjoid3VwZWlxaSIsInVzZXJfaWQiOjF9.xj-7qSts6Yg5Ui55-aUOHJS4KSaeLq5weXMui2IIEJU"
    payload = get_payload(token)
  • drf-jwt 与 flask-jwt 代码示例

链接:https://pan.baidu.com/s/1g9akaYauenK7nh_dnMON0A

提取码:bnwf

扩展与总结

djangorestframework-jwt本质是调用pyjwt实现. pyjwt更好用,可以支持其他框架使用(一招鲜吃遍天).

优点:

因为json的通用性,所以JWT是可以跨语言支持的,像C#,JavaScript,NodeJS,PHP等许多语言都可以使用

因为由了payload部分,所以JWT可以在自身存储一些其它业务逻辑所必要的非敏感信息,便于传输,

jwt的构成非常简单,字节占用很小,所以它是非常便于传输的,它不需要在服务端保存会话信息,所以它易于应用的扩展.

安全相关:

不应该在jwt的payload部分存储敏感信息,因为该部分是客户端可解密的部分,保护好secret私钥。该私钥非常重要,如果可以请使用https协议

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 初始SQL语句 简单使用

    郭楷丰
  • django视图 CBV 和 FBV

    郭楷丰
  • Linux基础学习5

    systemctl list-unit-files |grep sshd 查看服务是否开机自启动

    郭楷丰
  • Spring Cloud中Feign如何统一设置验证token

    原理是通过每个微服务请求之前都从认证服务获取认证之后的token,然后将token放入到请求头中带过去,这样被调用方通过验证token来判断是否合法请求。

    猿天地
  • 简单理解Token机制

    互联网发展到现在已经到了一个非常成熟的时代,所以不再是一个你写一个静态网站就可以进行疯狂盈利的时代了。现在对产品有着很多的要求,健壮性,安全性这...

    逆月翎
  • Laravel 前后端分离项目中 Jwt-Auth + Vue 平滑刷新 Token

    Token 翻译为令牌,就是鉴别身份的凭据,类似于身份证;token 本质就是一大串字符串,最常用的场景就是接口对接的鉴权。token 通过一次登录验证,得到一...

    蓝默空间
  • 聊聊 OAuth 2.0 的 Token 续期处理

    若上,当 前端拿着正确的(未过期且未使用过)refresh_token 去调用 认证中心的刷新 端点刷新时,会 触发RefreshTokenGranter, 返...

    冷冷
  • 基于token的多平台身份认证架构设计

    基于token的多平台身份认证架构设计 1   概述 在存在账号体系的信息系统中,对身份的鉴定是非常重要的事情。 随着移动互联网时代到来,客户端的类型越来越多,...

    用户1170933
  • 使用python实现后台系统的JWT认证

    專 欄 ❈ 茶客furu声,Python中文社区专栏作者 博客: http://www.jianshu.com/p/537b356d34c9 ❈ ...

    Python中文社区
  • 使用Identity Server 4建立Authorization Server (4)

    上一篇讲了使用OpenId Connect进行Authentication. 下面讲 Hybrid Flow和Offline Access 目前我们解决方案里面...

    solenovex

扫码关注云+社区

领取腾讯云代金券