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