上一篇講完了 Cookie,那 Session 又是什麼?
Session 就像是麥X勞的點點卡,給顧客一個卡片,只要顧客使用這張卡片,商店本身就可以查到使用者的資料。
Session 也是一樣,交給使用者一筆 Cookie,裡面記錄著一些資訊,並且(理論上應該只有) Server 可以取得有關的資訊。
看到這邊是不是還不知道資訊是如何記錄的、又記錄在哪對吧!因為又可以細分為兩種:
Server Side Session
資訊儲存在 Server 那側(對,我沒說在 Server 上,因為資料庫可以跟 Server 分開),並且 Server 只交給使用者一個 session_id。只要使用者拿著這個 ID,Server 就可去找到資料來認識使用者(前提是 Session 沒過期)。
就類似會員卡一樣,卡片本身不紀錄任何除了卡號以外的所有資訊,顧客拿著會員卡,刷一下卡號就可以在商店的紀錄上找到這個使用者,而卡號本身並沒有任何意義。
Client Side Session
資訊加密過後(重點就是這個加密,不加密就屬於 Cookie 了),儲存在 Client 的 Cookie 上,並且(理論上應該只有) Server 端能夠解密看到原始的資訊。
就類似悠遊卡一樣(雖然這個舉例並不好,但 get 到重點就好),卡片本身紀錄了一部分資訊(不太可能全部啦,全部的話 Cookie 早就爆掉了),悠遊卡上面記錄著一部分加密後的資訊,但是只有商店能夠解密獲得原本的資訊。
大概知道了 Session 的分類了之後,那 Flask 又屬於哪一種呢?
Flask 本身所使用的 Session 是屬於 Client Side Session。要做到 Server Side Session 可以透過 Flask-Session 這個擴充套件達成。
在開始 Session 前要先設定好 SECRET_KEY,如何設定 SECRET_KEY 呢?
首先要先生成一個 SECRET_KEY,直接在 cmder 執行這行。
python -c "import os;print(os.urandom(16))"
執行完後界可以得到一組隨機產生的 SECRET_KEY,然後在 app.py
中設定(或是放在設定檔後載入)。
app.py
from flask import Flask, session
app = Flask(__init__)
# 設定好剛剛的 SECRET_KEY,提醒一下,這個最好自己生成喔!
app.config['SECRET_KEY'] = b'>\x89k\xff.t{\xed\xc0\x8c^E\x81A\xe7\xb6'
其他相關設定
# PERMANENT_SESSION_LIFETIME:設置 session 的有效期 = Cookie 的過期時間,單位是秒。默認 Session 是永久,當 session.permanent 為 True 時才會套用。
# SESSION_COOKIE_NAME: 返回給客戶端的 Cookie 的名稱,默認是 "session"
# SESSION_COOKIE_DOMAIN: 設置 Session 的 Domain
# SESSION_COOKIE_PATH: 設置 Session 的 Path
# SERVER_NAME: 設置 Server name,不常使用
# SESSION_COOKIE_SECURE: 如果為 True,那麽只會使用 HTTPS 發送,默認為 False。
# APPLICATION_ROOT: 根路徑。
# SESSION_REFRESH_EACH_REQUEST: 是否應該為每一個請求設置cookie,默認為True,如果為False則必須顯性調用set_cookie函數;
# SESSION_COOKIE_HTTPONLY:默認為 True,表示允許 JavaScript 使用 Cookie
這樣就可以了。接著改原本的架構:
ithome
├── static
│ └── logo.svg
├── templates
│ ├── res
│ │ ├── home.html
│ │ ├── index.html
│ │ ├── login.html
│ │ ├── page_not_found.html
│ │ └── settings.html
│ └── base.html
├── app.py
├── configs.py
├── Pipfile
└── Pipfile.lock
app.py
@app.route('/')
def index():
return render_template('res/index.html')
@app.route('/home', methods=['GET'])
def home():
if 'username' in session:
user = session['username']
else:
user = None
return render_template('res/home.html', username=user)
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET': # 輸入網址會進到這裡
response = make_response(render_template('res/login.html'))
# expire_date = datetime.datetime.now() - datetime.timedelta(days=30)
# response.set_cookie('username', '')
elif request.method == 'POST': # 表單送出後會到這裡
account = request.values.get('username', None)
# 驗證是否有這個使用者以及密碼是否正確,生出驗證結果 auth_result
auth_result = 'success' # 假設成功
''' 建立回應 '''
if auth_result == 'success': # 如果都正確
response = make_response(redirect(url_for('home')))
''' 設定 Session '''
session['username'] = account
else: # 如果錯誤
response = make_response(redirect(url_for('login')))
else:
response = make_response(redirect(url_for('index')))
return response
@app.route('/settings', methods=['GET'])
def settings():
if 'username' in session:
user = session['username']
else:
user = None
return render_template('res/settings.html', username=user)
大概就這樣就可以了,不用特別將 Session 塞入 response,因為 Flask 會自動帶入。
如果想要達成 Server Side Session,可以透過 Flask_session 這個套件達成,使用方式大致相同,只是除了上面設定的部分以外,多了一些關於如何儲存的設定而已。
SESSION_TYPE: 設定如何儲存。選項有下面這幾種
null(default): 使用 Flask 預設的方式。(你都特別裝了這個插件,用點其它的不好嗎?其它的不香嗎?就非得用它嗎?)
redis: 就用 Redis 的 Type 存在 Redis 裡面,Redis 會儲存在記憶體裡面。
相關設定:
SESSION_REDIS: Redis 的位置,預設為: 127.0.0.1:6379
memcached: 跟 Redis 差不多,只是變成是用 MemCache 存在記憶體裡面。
相關設定:
SESSION_MEMCACHED: MemCache 的位置,預設為: 127.0.0.1:11211
filesystem: 存在文件中。
相關設定:
SESSION_FILE_DIR: 文件位置,預設為目前工作資料夾。
SESSION_FILE_THRESHOLD: Session 最大項目數,預設為 500。
SESSION_FILE_MODE: 文件模式,預設為 0600(大概就是 chmod 0600 的意思)。
mongodb: 就是存在 MongoDB 中。
相關設定:
SESSION_MONGODB: MongoDB 的位置,預設為: 127.0.0.1:27017。
SESSION_MONGODB_DB: 大概就是 MongoDB 的資料庫名稱的意思,預設為: "flask_session"。
SESSION_MONGODB_COLLECT: 大概就是 MongoDB 的資料表名稱的意思,預設為: "sessions"。
sqlalchemy: 存在關聯式資料庫中。
相關設定:
SESSION_SQLALCHEMY: SQLAlchemy 的實例。資料庫 URL 使用 SQLALCHEMY_DATABASE_URI 的設定。
SESSION_SQLALCHEMY_TABLE: 資料表名稱,預設為: "sessions"。
SESSION_PERMANENT: Session 期限是否為永久,預設為 True。
SESSION_USE_SIGNER: 加密 Session,預設為 False;設為 True 需設置 SECRET_KEY。
SESSION_KEY_PREFIX: 存在資料庫中的 KEY 的前綴,預設為 session"。
那麼就大概這樣,Cookie 跟 Session 在網頁的技術中是基礎但很重要的技術,真的要學好。
大家掰~掰~