cookie、session与token的学习记录

cookie

Set-Cookie有name和value两个重要的属性(具体属性网上搜)
服务器会填充这两个值,然后发送给客户端,客户端在此后每次请求都会带上cookie

session

session设置结束会话的时间,和session_id(没有规律的字符串)

cookie保存session标识身份的信息(也是只有这个最重要)。对含有session——ID的cookie进行签名
session可以存在缓存中

flask框架session存储有两种方式:
第一种方式:直接存在客户端的cookies中

第二种方式:存储在服务端,如:redis,memcached,mysql,file,mongodb等等,存在flask-session第三方库

session存储的消息

  1. 身份信息、登陆状态 2. 用户的个性配置、权限列表 3. 其他的一些通用数据

axios不支持跨域使用cookie

flask中关于cookie与session的用法
具有不安全、不正确或缺少SameSite属性的Cookie
SameSite cookies

token令牌

JWT payload 与JWT header
后端核对用户名和密码成功后,将包含用户信息的数据作为JWT的Payload,将其与JWT Header分别进行Base64编码拼接后签名,形成一个JWT Token,形成的JWT Token就是一个如同lll.zzz.xxx的字符串
对以下三篇文章学习,尝试写出token创建与认证的函数
JWT详解
token创建
jwt在项目中的应用

以jwt思想生成的token的在线解析网站

json.dump()函数解析
separators=(‘,’, ‘:’)参数是用来序列化时消除空格的
python字符串前b、r、u、f的作用
以 f开头表示在字符串内支持大括号内的python 表达式
b" "前缀表示:后面字符串是bytes 类型。网络编程中,服务器和浏览器只认bytes 类型数据。
base64的使用
hmac用法

为了便于理解,废话版实现的token创建与token验证函数

import base64,json,hashlib,hmac,time

salt = 'helloworld'
timeout = 360

# 返回token字符串
def create_token(user_name,exp = timeout,salt = salt): # exp单位为秒
    # token有三个部分,分别为headers,payload,signature
    headers={
        'algorithm': 'HS256',
    }
    payload = {
        'user_name': user_name,
        "exp": int(time.time()+exp)# 过期时间戳
    }
    # 使用Base64 URL算法将headers的JSON对象先转码再转为字符串保存
    # 由于标准的Base64编码后可能出现字符+和/,在URL中就不能直接作为参数,
    # 所以可以使用urlsafe_b64encode的base64编码,其实就是把字符+和/分别变成-和_:
    headers_str =  json.dumps(headers, separators=(',', ':')) # 将python对象将对象中的空格去除,然后转为字符串
    headers_bytes = headers_str.encode('utf-8') # 由于base64编码函数输入的类型需要为字节,这里将字符串转为bytes
    headers_base64 = base64.urlsafe_b64encode(headers_bytes).replace(b'=', b'')#编码结束后得到的是bytes类型,(后
    #面原因是我自己猜的,不保真。由于base64编码填充会用到=,url传参时会被转义,直接删掉,后面解码的时候再补上会比较好
    headers_base64_str  = headers_base64.decode('UTF-8')  # 得到字符串
    
    first = headers_base64_str  

    #  header和payload可以直接利用base64解码出原文,
    # 从header中获取哈希签名的算法,从payload中获取有效数据

    # 加密payload(下面这一串,不再一步步说了)
    second = base64.urlsafe_b64encode(
        json.dumps(payload, separators=(',', ':')).encode('utf-8').replace(b'=', b'')).decode(
        'utf-8').replace('=', '')
        
    # 签名 把前两部分拼接之后,用哈希加密把签名两部分加密得到一个字符串
    # 拼接前两部分
    first_second = f"{first}.{second}"

    # 对前面两部分签名
    third = base64.urlsafe_b64encode(
        hmac.new(salt.encode('utf-8'), first_second.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8').replace('=','')

    # 拼接签名和前两部分,就叫做token啦
    token = ".".join([first, second, third])
    return token


def  verify_token(token,salt = salt,exp = timeout):
    token_list = token.split('.')
    headers = token_list[0]
    payload = token_list[1]
    signature = token_list[2]
    # 应该返回的数据
    result = {
        'valid' : False,
        'msg' : ''
    }
    # 判断签名是否有效
    headers_payload = f"{headers}.{payload}"
    new_signature = base64.urlsafe_b64encode(
        hmac.new(salt.encode('utf-8'), headers_payload.encode('utf-8'), hashlib.sha256).digest()).decode(
        'utf-8').replace('=','')
    if(new_signature == signature):
        if isinstance(payload, str):
            payload = payload.encode('ascii')
        rem = len(payload) % 4
        if rem > 0:
            payload += b'=' * (4 - rem)
        # 上面这一部分是解密的部分数据补全格式

        payload_data = base64.urlsafe_b64decode(payload)  # 解码
        data = json.loads(payload_data)  # 加载payload信息为可以通过get方法获取里面的值

        payload_exp = data['exp']
        if( isinstance(payload_exp, int) and payload_exp<int(time.time()+exp)): # 保证payload_exp是个有效数值
            result['valid'] = False
            result['msg'] = 'token已失效'
        else:
            result['valid'] = False
            result['msg'] = 'token认证失败'
    else:
        result['valid'] = False
        result['msg'] = '非法的token'
    return result
create_token(user_name='hh')
print(verify_token(“eyJhbGdvcml0aG0iOiJIUzI1NiJ9.eyJ1c2VyX25hbWUiOiJoaCIsImV4cCI6MTY2MTY2ODA2MX0.4EnhYvt90zCKpg_i4wYBylPaUg9bfiI2H4FktEc13CU”))

输出:
在这里插入图片描述

简洁点的:

import base64,json,hashlib,hmac,time

salt = 'helloworld'
timeout = 360

# 返回token字符串
def create_token(user_name,exp = timeout,salt = salt): # exp单位为秒
    # token有三个部分,分别为headers,payload,signature
    headers={
        'algorithm': 'HS256',
    }
    payload = {
        'user_name': user_name,
        "exp": int(time.time()+exp)# 过期时间戳
    }

    first = base64.urlsafe_b64encode(
        json.dumps(headers, separators=(',', ':')).encode('utf-8').replace(b'=', b'')).decode(
        'utf-8').replace('=', '')

    second = base64.urlsafe_b64encode(
        json.dumps(payload, separators=(',', ':')).encode('utf-8').replace(b'=', b'')).decode(
        'utf-8').replace('=', '')
    first_second = f"{first}.{second}"
    third = base64.urlsafe_b64encode(
        hmac.new(salt.encode('utf-8'), first_second.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8').replace('=','')
    token = ".".join([first, second, third])
    return token

def  verify_token(token,salt = salt,exp = timeout):
    token_list = token.split('.')
    headers = token_list[0]
    payload = token_list[1]
    signature = token_list[2]
    # 应该返回的数据
    result = {
        'valid' : False,
        'msg' : ''
    }
    # 判断签名是否有效
    headers_payload = f"{headers}.{payload}"
    new_signature = base64.urlsafe_b64encode(
        hmac.new(salt.encode('utf-8'), headers_payload.encode('utf-8'), hashlib.sha256).digest()).decode(
        'utf-8').replace('=','')
    if(new_signature == signature):
        if isinstance(payload, str):
            payload = payload.encode('ascii')
        rem = len(payload) % 4
        if rem > 0:
            payload += b'=' * (4 - rem)
        # 上面这一部分是解密的部分数据补全格式

        payload_data = base64.urlsafe_b64decode(payload)  # 解码
        data = json.loads(payload_data)  # 加载payload信息为可以通过get方法获取里面的值

        payload_exp = data['exp']
        if( isinstance(payload_exp, int) and payload_exp<int(time.time()+exp)): # 保证payload_exp是个有效数值
            result['valid'] = False
            result['msg'] = 'token已失效'
        else:
            result['valid'] = False
            result['msg'] = 'token认证失败'
    else:
        result['valid'] = False
        result['msg'] = '非法的token'
    return result


vue中axios解决跨域问题和拦截器使用
跨域资源访问
flask-cors的配置
浏览器的预检请求

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值