flask中的session cookie 测试 和 项目中的用户状态保持
# -*- coding:utf-8 -*- # Author: json_steve from flask import Flask, current_app, make_response, request, session app = Flask(__name__) app.secret_key = '123' @app.route('/') def index(): response = make_response('jsonsteve') # response.headers['Set-Cookie'] = 'heads' response.set_cookie('a','1',max_age=3600) return response @app.route('/get_cookie') def get_cookie(): print request.cookies # {'heads; a': u'1'} # k = request.cookies['heads; a'] # cookie的获取 k = request.cookies['a'] # 获取不到 报错 print k return 'get_cookie %s' % k @app.route('/delete_cookie') def delete_cookie(): response = make_response('delete_success') response.delete_cookie('a') return response @app.route('/set_session') def set_session(): session['name'] = 'jsonsteve' # 设置sesssion return 'set_success' @app.route('/get_session') def get_session(): name = session.get('name') # 获取session 存哪里去了 return name if __name__ == '__main__': app.run(debug=True) cookie测试 当访问http://127.0.0.1:5000/ 时,服务器回给浏览器的 Response Headers: Content-Length:9 Content-Type:text/html; charset=utf-8 Date:Sat, 23 Dec 2017 10:12:53 GMT Server:Werkzeug/0.12.2 Python/2.7.11+ Set-Cookie:heads Set-Cookie:a=1; Expires=Sat, 23-Dec-2017 11:12:53 GMT; Max-Age=3600; Path=/ 1,Content-length:9 是因为返回的消息实体是9个字节,因为make_response('jsonsteve')。 2,response.headers['Set-Cookie'] = 'headers' 实际就是直接设置响应头,此设置的cookie过期时间是浏览器会话结束时。 3,response.set_cookie('a','1',max_age=3600) 这种设置cookie的方式过期时间是3600s。 4,如果response.headers['Set-Cookie'] = 'headers'写到response.set_cookie('a','1',max_age = 3600)的后面,则只产生一个cookie就是headers 5,headers是cookie的内容,名字是空。 当访问http://127.0.0.1:5000/get_cookie,获取cookie的时候,浏览器会向服务器发送的请求头: RequestHeaders: Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding:gzip, deflate, sdch Accept-Language:zh-CN,zh;q=0.8 Cache-Control:max-age=0 Connection:keep-alive Cookie:heads; a=1 Host:127.0.0.1:5000 Upgrade-Insecure-Requests:1 User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 请求头的cookie实际是有两个,由于flask将cookie封装成字典在request.cookies里,但是有一个cookie没有名字,只有值headers,所以封装成了这样{'heads; a': u'1'},注意键是‘heads; a’。 其次不同的浏览器,或者再此基础上你又设置了一个response.set_cookie('b','2',max_age=3600),这时浏览器再次访问服务器,发送的cookie就可能是Cookie:a=1;b=2;headers,但是这种情况向flask的request.cookies就变成{'a': u'1', 'b': u'2'},headers没了,太乱了,就别用response.headers['Set-Cookie']设置啦。 注意:response.delete_cookie('a') 虽然是delete但是不是删除名字是a的cookie,而是设置a的值是空,过期时间是0 回复的http头是: Set-Cookie:a=; Expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/ session测试 当浏览器访问 http://127.0.0.1:5000/set_session时,服务器回给浏览器 ResponseHeaders: Content-Length:11 Content-Type:text/html; charset=utf-8 Date:Sat, 23 Dec 2017 11:34:27 GMT Server:Werkzeug/0.12.2 Python/2.7.11+ Set-Cookie:session=eyJuYW1lIjp7IiBiIjoiYW5OdmJuTjBaWFpsIn19.DR_Qww.V_Xekew9d9O_PeH2y8ujB9RCYMw; HttpOnly; Path=/ 也就是说,flask的session默认是放到cookie里,名字是session,最后存储在浏览器的,对存储的session的键值是加密的,这是使用session必须设置app.secret_key = '123'密钥的原因。密钥的生成方法一般是在终端生成随机数 1 >>> import os,base64 >>> base64.b64encode(os.urandom(48)) '/V9pfTLaYKnyGYhnzGqYlnYDEee2UksbMkFmSXG4ZtCNfhVCHs4BnOclPtg2RHbf' 注:在每次访问http://127.0.0.1:5000/get_session,访问session时,flask又会重新对session加密,所以cookie中的session名字所对应的内容会变化。 项目中的用户状态保持 一般项目会把session保存到服务器(redis),所以在设置config是可以这样设置 # redis链接配置 REDIS_HOST = '127.0.0.1' REDIS_PORT = 6379 SESSION_TYPE = "redis" # 设置保存到的redis,默认如果没设置话,Flask-Session会帮我们创建一个redis SESSION_REDIS = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT) # 签名 SESSION_USE_SIGNER = True # 设置过期时间 PERMANENT_SESSION_LIFETIME = 86400 不要忘记Session初始化 from flask_session import Session Session(app) 在登陆时将登陆信息发送给后台服务器: var params = { "mobile": mobile, "password": password, }; $.ajax({ url:"/api/v1.0/session", method: "post", headers: { "X-CSRFToken": getCookie("csrf_token") }, data: JSON.stringify(params), contentType: "application/json", success: function (resp) { if (resp.errno == "0") { location.href = "/index.html" }else { $("#password-err span").html(resp.errmsg); $("#password-err").show() } } }) 后台服务器接收到用户信息后将信息存储到session中,而session存到了redis里。 保存用户登录状态 session["user_id"] = user.id session["mobile"] = user.mobile session["name"] = user.name 如果访问需要登陆的网页,如何确定用户登陆了呢,可以写一个装饰器: def login_required(f): @functools.wraps(f) # __name__还是原来的 def warrper(*args, **kwargs): user_id = session.get('user_id') if not user_id: return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录') else: g.user_id = user_id return f(*args, **kwargs) return warrper 就是去session里看一下又没user_id,因为session是请求上下文,所以不同的请求session也是不同的所以不用担心session会不会混乱。