This page looks best with JavaScript enabled

Flask自带的Session

 ·  ☕ 2 min read

今天才搞懂 Flask 自带的 session 竟然是完全依靠客户端的。

  • 当写入值到 session 中后, session 就会比加密成一个字符串,然后写入到 cookie 里
  • 当一个请求来时,获取请求的 cookie 里拿到 session 字符串,然后解析到 session 字典里

之前还使用自带的 session 做用户登录,现在看来不安全,用户是否登录完全依赖了客户端呀。本以为 Flask 自带的 session 是储存在内存中的,结果现在清楚了,内存中没有存,都是每次从请求的 cookie 中拿到,然后解析成 dict.

使用 session 的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def login():
    data = request.json
    password = data.get('password')
    account = data.get('account')
    user = UserDao.get_by_args(password, account)
    if not user:
        return jsonify(status='false', message=u'密码错误'), 401
    session[user['id']] = user['name']
    resp = Response(json.dumps({'status': 'ok', 'user': user}), mimetype='application/json')
    set_cookie(resp, 'u_id', str(user['id']), max_age=USER_LOGIN_MAX_AGE)
    return resp

登录验证:

这个验证就没有什么意义了,如果cookie中有 u_id,那么 session 中就一定有 u_id …. 因为 session 就是从 cookie 来的

1
2
3
4
5
6
7
8
9
def authorize(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        u_id = request.cookies.get('u_id')
        authorized = u_id and session.get(u_id)        
        if not authorized:
            return jsonify(message=u"需要登录"), 401
        return func(*args, **kwargs)
    return wrapper

看来登录验证不能使用这个 session 简单的判断了,需要通过其他方式存储登录成功的 u_id,比如存到 Redis

结合 Redis 改进之后的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def login():
    data = request.json
    password = data.get('password')
    account = data.get('account')
    user = UserDao.get_by_args(password, account)
    if not user:
        return jsonify(status='false', message=u'密码错误'), 401    
    resp = Response(json.dumps({'status': 'ok', 'user': user}), mimetype='application/json')
    set_cookie(resp, 'u_id', str(user['id']), max_age=USER_LOGIN_MAX_AGE)
    redis_client.sadd('logined_user_ids', user['id'])
    return resp
1
2
3
4
5
6
7
8
9
def authorize(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        u_id = request.cookies.get('u_id')
        authorized = u_id and redis_client.sismember('logined_user_ids', u_id)
        if not authorized:
            return jsonify(message=u"需要登录"), 401
        return func(*args, **kwargs)
    return wrapper
Support the author with
alipay QR Code
wechat QR Code

Yang
WRITTEN BY
Yang
Developer