簡體   English   中英

Flask CSRF Protection在響應標頭上設置無效的Set-Cookie

[英]Flask CSRF Protection setting invalid Set-Cookie on response headers

我正在使用Flask和Firebase身份驗證創建產品目錄。 我正在關注如何使用預先構建的用戶界面和會話Cookie設置客戶端和服務器的文檔,如下所述: https//firebase.google.com/docs/auth/admin/manage-cookies

GET請求正常工作,服務器驗證每個請求的會話cookie並相應地發送內容。 但是,當我執行POST請求(例如,提交表單以創建新項目)時,服務器無法解析cookie。

\n

我使用Chrome開發工具驗證了會話cookie在GET和POST請求上發送到服務器的情況都是相同的。 嘗試了幾件我發現谷歌搜索類似問題的事情,但有些事情都有效。 我也嘗試在這里找到一個類似的問題,但我還沒有找到。

編輯:幾個小時再看看問題,我發現GET和POST請求中的cookie不一樣。 我查看了Chrome Dev Tools的請求,我發現GET響應返回一個帶有無效cookie的Set-Cookie標頭(是什么使POST請求有一個無效的cookie並再次重定向到登錄頁面) 。

這只發生在需要登錄的頁面上(如果你沒有登錄則重定向到登錄頁面),但我仍然無法找到Flask發送帶有無效cookie的Set-Cookie標頭的原因。

EDIT2:經過幾個小時后,我發現從這些頁面上的表單中刪除CSRF隱藏輸入修復了cookie問題(GET請求沒有創建Set-Cookie),所以它必須與CSRF的事情,但我不知道如何。 使用CSRF時會話cookie有什么特殊的行為,我沒有考慮到這一點嗎?

“新項目”模板:

{% extends "layout.html" %}

{% block title %}
    New item
{% endblock %}

{% block head %}
    {{ super() }}
    <link rel="stylesheet" type="text/css" media="screen" href="{{ url_for('static', filename='form.css') }}">
{% endblock %}

{% block content %}
<form action="{{ url_for('newItem') }}" method = 'post'>
    <h1>Create a new item</h1>
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
    <label>Name</label>
    <input type='text' size='30' name='name' placeholder="Name" required>
    <label>Description</label>
    <textarea rows='4' name='description' placeholder="Description" required></textarea>
    <label>Price</label>
    <input type='text' size='30' name='price' placeholder="Price" required>
    <label>Image URI</label>
    <input type='text' size='30' name='image' placeholder="https://example.com/image.png" required>
    <label>Category</label>
    <select name='category' required>
        {% for c in categories %}
        <option value="{{ c.id }}">{{ c.name }}</option>
        {% endfor %}
    </select>
    <input type='submit' value='Create'>
    <a href="{{ url_for('categories') }}">Cancel</a>
</form>
{% endblock %}

“需要登錄”裝飾者:

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        session_cookie = request.cookies.get('session')
        # Verify the session cookie. In this case an additional check is added to detect
        # if the user's Firebase session was revoked, user deleted/disabled, etc.
        try:
            decoded_claims = auth.verify_session_cookie(session_cookie, check_revoked=True)
            return f(*args, **kwargs)
        except ValueError as e:
            # Session cookie is unavailable or invalid. Force user to login.
            print(e)
            return redirect(url_for('login', mode="select", signInSuccessUrl=request.url))
        except auth.AuthError as e:
            # Session revoked. Force user to login.
            print(e)
            return redirect(url_for('login', mode="select", signInSuccessUrl=request.url))
    return decorated_function

“Items”端點(按預期工作):

@app.route('/items/<int:item_id>/')
def item(item_id):
    session = DBSession()
    item = session.query(Item).get(item_id)

    session_cookie = flask.request.cookies.get('session')
    # Verify the session cookie. In this case an additional check is added to detect
    # if the user's Firebase session was revoked, user deleted/disabled, etc.
    try:
        auth.verify_session_cookie(session_cookie, check_revoked=True)
        return render_template('item.html', item=item, logged=True)
    except ValueError as e:
        # Session cookie is unavailable or invalid. Force user to login.
        print(e)
        return render_template('item.html', item=item, logged=False)
    except auth.AuthError as e:
        # Session revoked. Force user to login.
        print(e)
        return render_template('item.html', item=item, logged=False)

“New Item”端點(將帶有無效cookie的Set-Cookie標頭返回給GET請求):

@app.route('/items/new/', methods=['GET', 'POST'])
@login_required
def newItem():
    session_cookie = flask.request.cookies.get('session')
    decoded_claims = auth.verify_session_cookie(session_cookie, check_revoked=True)

    session = DBSession()
    categories = session.query(Category).all()
    if request.method == 'GET':
        return render_template('new_item.html', categories=categories, logged=True)
    else:
        # SOME LOGIC HERE
        # [...]
        return redirect(url_for('item', item_id = newItem.id))

我在POST請求中遇到的錯誤如下:

Value Error
Can't parse segment: \���

為了解決這個問題,我將cookie名稱從'session'更改為任何其他名稱。 我不知道為什么Flask會繼續為'session'cookie發送Set-Cookie標頭,所以如果有人知道為什么請評論它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM