本文链接:https://www.jianshu.com/p/721d54e83190
作者:西瓜甜
1. 安装包
pip3 install redis
2. 连接
In [1]: import redis
In [2]: rs = redis.StrictRedis(host='192.168.1.37', port=6379,db=0,decode_responses=True
In [3]: rs.set("QF", "www.qfedu.com")
Out[3]: True
In [4]: rs.get("QF")
Out[4]: 'www.qfedu.com'
db=0
指定使用那个数据库,0-15
共 16 个,默认是0
decode_responses=True
redis 返回值默认是二进制 bytes 类型,设置为True
可直接返回字符串,默认使用utf-8
3. 基本操作
4.1 set 在 Redis 中设置键值对值,默认,不存在则创建,存在则修改
set(name, value, ex=None, px=None, nx=False, xx=False)
"""
参数:
ex,过期时间(秒)
px,过期时间(毫秒)
nx,假如设置为True,则只有 name 不存在时,当前 set 操作才执行
xx,假如设置为True,则只有 name 存在时,当前 set 操作才执行
"""
- 示例
In [121]: rs.set("name", "shark",ex=50)
Out[121]: True
In [122]: rs.ttl("name") # 查看过期时间
Out[122]: 41
In [123]: rs.get("name")
Out[123]: 'shark'
4.2 setex 设置键值对,并设置过期时间(单位秒)
setex(name, time, value)
"""
参数:
time,过期时间(数字秒)
"""
- 示例
In [26]: rs.setex('login', 30, 1)
Out[26]: True
In [27]: rs.ttl("login")
Out[27]: 27
In [28]: rs.get("login")
Out[28]: '1'
4.3 Hash 操作
Redis 中的 Hash 数据,很想 Python 中嵌套的字典 : {"n1": {"k1": "v1", "k2", "v2"}}
使用场景
比如我们想存储用户的登录信息
一般用户的登录信息有一下几点:
- 用户名 name
- 加密的密码 password
- 会话 session_id
- 会话过期时间 expiration_date
那现在就来模拟一下一个用户从登录到登出(过期)的情况
4.3.1 具体实现
当用户登录的时候我们需要添加多个数据,可以使用 hmset()
方法
"""
hmset(name, mapping)
name 就是一个hash 的名字 , mapping 就是一个字典
在name对应的hash中批量设置键值对,没有的 key 就创建,已存在的 key 修改
"""
In [78]: import random, string, hashlib
In [79]: name="shark"
In [80]: base_str = f"{string.digits + string.ascii_letters}"
In [81]: sessid = ''.join(random.sample(base_str, 20))
In [82]: sessid
Out[82]: 'SFMNr3jzJZTRYLy64qfb'
In [83]: password = hashlib.md5("QFedu123!".encode('utf-8'))
In [84]: password = password.hexdigest()
In [85]: password
Out[85]: '19b169cff70f61b4e80663757025a17d'
In [86]: user_info = {"name": name, "password": password, "sessid": sessid}
In [87]: rs.hmset(name, user_info)
Out[87]: True
In [88]: rs.setex(f"{name}_sessid",86400,sessid))
Out[88]: True
每次用户再次跳转页面或者发送新的请求时,我们都应该查看他的登录状态和会话是否超时。
首先,获取 redis 中 Hash 数据使用的是 hget()
和 hmget
方法
hget(name,key)
在name对应的hash中获取根据key获取value
In [155]: rs.hget(name, 'sessid')
Out[155]: 'SFMNr3jzJZTRYLy64qfb'
hmget(name, keys, *args)
在name对应的hash中获取多个key的值
参数:
name,reids对应的name
keys,要获取key集合,例如:['k1', 'k2', 'k3']
*args,要获取的key,例如:k1,k2,k3
In [156]: rs.hmget(name, ["name", "sessid", "login"])
Out[156]: ['shark', 'SFMNr3jzJZTRYLy64qfb', 'True']
In [157]: name, sessid, login = rs.hmget(name, ["name", "sessid", "login"])
In [158]: login
Out[158]: 'True'
模拟登录状态OK, 需要进一步检查 会话是否超时的情况
In [164]: rs.hmset(name, {"sessid": '', "login": "False"})
Out[164]: True
In [165]: rs.hget(name,"sessid")
Out[165]: ''
In [166]: rs.hget(name,"login")
Out[166]: 'False'
作业练习:
编写一个脚本,把上面我们讲的用户信息存入到 Redis 中。
实现一个简单的登录验证功能。
-
提示用户登录,用户输入用户名和密码,首先验证用户名密码
-
用户名密码错误,请重新登录。
-
用户名密码正确就继续验证,会话是否存在或者是否过期
-
会话过期或者不存在,则重新设置或添加会话信息, 并显示登录成功
-
不过期,就显示继续操作
流程图:
image.png运行时的效果
image.png
参考源码
配置文件
settings.py
CACHE_SERVER = {
"host": '127.0.0.1',
"port": 6379,
'db': 0
}
连接 Redis 模块
cache.py
import redis
from settings import CACHE_SERVER
# 缓存 Redis 连接信息
redis_host, redis_port = CACHE_SERVER.get("host"), CACHE_SERVER.get("port")
redis_db = CACHE_SERVER.get("db")
rs = redis.StrictRedis(
host=redis_host,
port=redis_port,
db=redis_db
)
程序源码
import random, string, hashlib
from cache import rs
def generate_sessid():
"""生产随机字符串
Return: 返回 session id
"""
# 获取基本的字符串0-9 a-z A-Z
base_str = f"{string.digits + string.ascii_letters}"
# 拼接
sessid = ''.join(random.sample(base_str, 20))
return sessid
def hash_pwd(pwd):
"""传入一串字符,进行 MD5 计算
Keyword arguments:
pwd -- 字符串
Return: md5 加密值
"""
password = hashlib.md5(pwd.encode('utf-8'))
return password.hexdigest()
def save_session(name, pwd, sessid=''):
"""组合用户会话信息,并存入缓存
Keyword arguments:
name -- 用户名
pwd -- 加密过的密码
sessid -- 会话 id
Return:
"""
user_info = {"name": name, "password": pwd, "sessid": sessid}
rs.hmset(name, user_info)
rs.setex(f"{name}_sessid",86400,sessid)
def auth(name, pwd):
source_pwd = hash_pwd("QFedu123!")
if name == 'shark' and pwd == source_pwd:
return True
else:
return False
if __name__ == "__main__":
while True:
inp = input("输入用户名和密码,中间用空格隔开,比如: shark 123\n>>:")
user_pwd = inp.split()
if len(user_pwd) == 2:
name, pwd = user_pwd
else:
print("格式错误")
continue
sessid = generate_sessid()
pwd = hash_pwd(pwd)
# 判断用户名和密码是否正确
if auth(name, pwd):
# 检查会话是否超时
ttl = rs.ttl(f"{name}_sessid")
if ttl >= 1:
print("会话有效")
print("继续操作")
break
else:
# 会话不存在或者失效,存入新的会话
save_session(name, pwd,sessid=sessid)
print("登录成功")
break
else:
print("用户名或者密码错误")
网友评论