Day 20 Flask Session

上一篇讲完了 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 在网页的技术中是基础但很重要的技术,真的要学好。

大家掰~掰~


<<:  [DAY27]GCP-Google Cloud Platform

>>:  [面试][资料库]如何解决高并发情境的商品秒杀问题

[Day 1] 身为一名普通 iOS 开发者讲讲干话 Intro

前言 Hi 我是一名普通的 iOS 开发者,兴趣使然的 UI 设计师。不小心参与了几年 iOS 开发...

Day24:今天我们来聊一下Azure Sentinel中使用的关注清单

Azure Sentinel提供资料表来储存可供Kusto查询语言(KQL)查询存取的清单资料。 A...

【DAY 28】Microsoft 365 X Dynamic 365该怎麽选才好呢? (中)

哈罗大家好~ 昨天我们初步认识了 Dynamic 365,那 Dynamic 365 与 Micro...

[30天 Vue学好学满 DAY3] 专案建置&除错套件

前置作业安装 node vue vue-cli vue-cli(Vue.js Command-Lin...

Day23 semaphore, mutex

前言 昨天花了很大的篇幅在学习spinlock ,可惜最重要的一部分 queued spinlock...