iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0

上一篇講完了 Cookie,那 Session 又是什麼?

Session

Session 就像是麥X勞的點點卡,給顧客一個卡片,只要顧客使用這張卡片,商店本身就可以查到使用者的資料。

Session 也是一樣,交給使用者一筆 Cookie,裡面記錄著一些資訊,並且(理論上應該只有) Server 可以取得有關的資訊。

看到這邊是不是還不知道資訊是如何記錄的、又記錄在哪對吧!因為又可以細分為兩種:

  1. Server Side Session

    資訊儲存在 Server 那側(對,我沒說在 Server 上,因為資料庫可以跟 Server 分開),並且 Server 只交給使用者一個 session_id。只要使用者拿著這個 ID,Server 就可去找到資料來認識使用者(前提是 Session 沒過期)。

    就類似會員卡一樣,卡片本身不紀錄任何除了卡號以外的所有資訊,顧客拿著會員卡,刷一下卡號就可以在商店的紀錄上找到這個使用者,而卡號本身並沒有任何意義。

  2. 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 在網頁的技術中是基礎但很重要的技術,真的要學好。

大家掰~掰~


上一篇
Day 19 Flask Cookie
下一篇
Day 21 Flask Blueprint
系列文
月光下的Flask之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言