问题场景:
在falsk项目中导入了两个session:
首先,配置文件config.py文件中 有个 flask_session扩展导入了Session ( from flask_session import Session );
然后,在login.py文件的登录接口中 有从flask导入了session (from flask import session);
先阐述一下状态保持的概念以及浏览器服务器如何实现状态保持:
1 状态保持:
有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等,
实现状态保持主要有两种方式:使用Cookie在客户端存储信息,使用Session在服务器端存储信息
1.1.Cookie:
▪Cookie是由服务器端生成,发送给客户端浏览器,浏览器会将Cookie的key/value保存,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。
▪应用:最典型的应用是判定注册用户是否已经登录网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登录手续,这些都是Cookie的功用。
▪提示:Cookie基于域名安全,不同域名的Cookie是不能互相访问的
如:访问jingdong.com时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到jingdong.com写的Cookie信息,浏览器的同源策略。
1.2.session:
对于敏感、重要的信息,建议要存储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息,在服务器端进行状态保持的方案就是Session,Session依赖于Cookie
2、区别:
2.1 当然,在flask项目中也要实现状态保持,把Cookie存储在浏览器,session存储到服务器,但是当我们的用户量较大时,各种状态保持信息(用户信息,浏览历史信息等)都放到session中,就会大大的增加服务器的负荷,为了减轻服务器的压力,我们就把session放到redis数据库中,另外,redis数据库读取数据也是更快的,这个功能的实现靠的就是flask-session扩展中的Session; 即session是基于浏览器的cookie进行保存在服务器上的,flask_session可以把session的值存储在redis数据库中。这个session无论用户登录还是退出,只要不过期,就一直存在,与框架无关,与语言无关,便于用户在浏览器端再次便捷登录。
2.2 from flask import session 这个sesssion是flask框架内置的请求上下文对象,用来操作记录http请求的数据或session信息,在请求过程中存在,请求结束后就被销毁;比如只有登录的用户并且发送http请求时,它才被唤醒存储内容,用户退出时,它又被销毁;在本flask项目的应用场景:
(1) 在登录接口,用户用过mobile 和password验证后(用户存在且密码正确),我们就通过mobile查询出该用户对象user, 再把该登录用户的name,user_id
, mobile 保存到上下文session中,方便其他模块接口的调用当前登陆的用户信息。
(2) 在登录接口实现登陆以后,我们如何在其他接口判断用户是否登录呢?很简单,我们只需用user_id = session.get("user_id"),如果user_id存在,就说明用户已经通过了登录接口的验证和session信息的保存。因为很多接口都要判断登录状态,我们通常把这个功能放到装饰其中(即重写flask_login的login_required方法),方便各接口调用
在utils/common.py文件中重写login_required
方法:
1 def login_required(func): 2 '''检查用户的登录状态''' 3 @wraps(func) 4 def wrapper(*args, **kwargs): 5 # 核心逻辑 获取session的id 6 user_id = session.get('user_id') 7 if user_id is not None: 8 # 表示用户已经登录 9 # 后面的接口仍需要user_id数据,来获取当前登陆的用户 10 # 为了方便,可以使用g变量来记录,避免多次访问保存session的redis服务器或项目服务器(根据session存放的位置) 11 g.user_id = user_id 12 return func(*args, **kwargs) 13 else: 14 retrun jsonify(error='4005', errmsg='用户未登录') 15 return wrapper
在其他接口的应用:(判断是否登录和获取登录用户id,这也是login_required的两个功能, 不重写的话只有判断功能)
1 from ihome.utils.common import login_required 2 3 @api.route("/sessions", methods=["DELETE"]) 4 @login_required # 验证登录装饰器 5 def logout(): 6 """登出""" 7 # 清除session数据, csrf_token需要保留. 8 csrf_token = session['csrf_token'] 9 session.clear() 10 session['csrf_token'] = csrf_token 11 12 # 删除session的方式:3种 13 # 1.session.pop() 2. 和Django所学相同 3. session.clear()全部删除 14 15 return jsonify(errno=RET.OK, errmsg="OK")