欧拉后台之 Python3 基于 JWT 的鉴权认证(一)

前情提要

毕业2年,一直没有可以拿出手的作品,怀着对于开源技术的热忱并且实现30岁前的财富自由的幻想,2021年伊始就在谋划着一项名为 "欧拉" 的项目,完整的设计整个项目的所有流程和
实现细节等问题,总体的规划如下,原型设计 + 前端技术 + 后台总结 + 发版优化四大模块进行开发设计,网上很多项目也都一叶障目,以偏概全居多,所以想要吃得好,自己动手实现是一个好办法。

JWT 是什么?

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

用途:
传统 IT 技术设计上,一般通过 session 保存用户的登录信息用来保存用户,因为 session 本身存在很多问题,所以目前互联网上较新的技术几乎都会选用 JWT 取代 session,
所以 JWT 最普遍的一个作用就是用来保存用户的登录信息;

1 session VS Jwt

session 工作原理:

session的数据一般存储在键值数据库(redis)上,储存的格式一般是这样:

session 缺点:

  • session数据通常保存在服务器端内存中,随着用户增多,服务端的开销会明显增大
  • 这种模式最大的问题是,没有分布式架构,无法支持横向扩展。如果使用一个服务器,该模式完全没有问题。但是,如果它是服务器集群或分布式结构的话,则需要一个统一的session数据库库来保存会话数据实现共享,这样负载均衡下的每个服务器才可以正确的验证用户身份。
  • sessionid储存在cookies上面的,所以也要做CSRF防护。cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。
  • 单点登录问题:难以适用于单点登录(Single Sign On : 简写SSO)的场景
  • 移动开发一般都不使用sessionid来保存登录状态

JWT 优点:
JWT的优点就是能解决上面session的所有缺点......最重要的可以有效地解决单点登录问题

JWT 工作流程:
1)用户登录成功后,服务器签发jwt,里面储存着用户的id等资料,用于标记用户的登录状态。注意!不能保存敏感信息,例如密码这些,具体原因下面有说。

2)然后在响应报文传送回去给客户端。

3)客户端收到之后,通过html5的 localStorage 或 sessionStorage 来保存JWT。

4)在下一次访问的时候,通过请求头把JWT带上,服务端收到之后,会进行校验,校验有没有修改过啊,有没有过期啊等。

5)校验通过之后,就可以成功登录了。

JWT 构成:
结构:header.payload.signature

# 头部.载荷.签名
# JWT示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

2 Python3 实现 JWT

import jwt,datetime
from jwt import exceptions

// 通过用户名和独属密钥生成基于时间的 TOKEN,传递给前端用于校验
def create_token(name,SECRET_KEY):
    strnow = datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S')
    '''基于jwt创建token的函数'''
    dic = {
        'exp': datetime.datetime.now() + datetime.timedelta(days=1),  # 过期时间
        'iat': datetime.datetime.now(),  # 开始时间
        'iss': name,  # 签名
        'data': {  # 内容,一般存放该用户id和开始时间
            'uuid':name,
            'time': strnow,
        },
    }

    token = jwt.encode(dic, key=SECRET_KEY, algorithm='HS256')
    # 返回生成的token
    return token

// 校验用户的 TOKEN 信息是否合法
def validate_token(token,SECRET_KEY):
    '''校验token的函数,校验通过则返回解码信息'''
    payload = None
    msg = None
    try:
        payload = jwt.decode(token, SECRET_KEY,algorithms=['HS256'])
        # jwt有效、合法性校验
    except exceptions.ExpiredSignatureError:
        msg = 'token已失效'
    except jwt.DecodeError:
        msg = 'token认证失败'
    except jwt.InvalidTokenError:
        msg = '非法的token'
    return (payload, msg)

总结

上述的基于 JWT 是实现网站入口的用户登陆保存用户登陆凭证的关键步骤,也是很多项目的最基本的交互过程,突破单点登录以后,完成用户的注册,登陆,保存用户登陆凭证以后,更多的功能就可以基于当前的实现进行灵活的扩展了,虽然简单也是需要深入思考的,这些技术点如果开发者自己搞清楚了,也就娴熟于心,慢慢就会得心应手的。只是对于很多新人来说,不自己上手开发实现就永远不会明白其中的奥秘。

单点登录(SSO)

单点登录就是登录一次,可以访问多个不同的子系统(不同的域名)。当你登录了淘宝之后,打开天猫后就自动登录,即使淘宝和天猫是不同的域名。如果没有单点登录的话,你登录了淘宝,再登录天猫,也是需要输入账号密码登录的。

posted @ 2021-09-15 20:11  流雨声  阅读(191)  评论(0编辑  收藏  举报