1. 程式人生 > >flask中的session cookie 測試 和 專案中的使用者狀態保持

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'金鑰的原因。金鑰的生成方法一般是在終端生成隨機數
>>> 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會不會混亂。