今天才搞懂 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
|