0 Câu hỏi: Flask CSRF Bảo vệ cài đặt Set-Cookie không hợp lệ trên các tiêu đề phản hồi

câu hỏi được tạo ra tại Wed, May 8, 2019 12:00 AM

Tôi đang tạo một danh mục sản phẩm bằng Xác thực Flask và Firebase. Tôi đang theo dõi tài liệu của họ về cách thiết lập cả máy khách và máy chủ bằng UI được xây dựng sẵn và Cookies phiên như đã nêu ở đây: https://firebase.google.com/docs/auth/admin/manage-cookies

Yêu cầu GET hoạt động tốt, máy chủ xác minh cookie phiên trên mỗi yêu cầu và gửi nội dung tương ứng. Nhưng khi tôi thực hiện một yêu cầu POST (chẳng hạn như gửi biểu mẫu để tạo một mục mới), máy chủ không thể phân tích cookie.

Tôi đã xác minh bằng Chrome Dev Tools rằng cookie phiên được gửi đến máy chủ trên cả hai yêu cầu GET và POST đều giống nhau. Đã thử một số điều tôi đã tìm thấy về những vấn đề tương tự nhưng bất cứ điều gì cũng có hiệu quả. Tôi cũng đã cố gắng tìm một câu hỏi tương tự ở đây nhưng tôi không tìm thấy câu hỏi nào.

EDIT: Sau một vài giờ xem xét lại vấn đề, tôi đã thấy rằng các cookie KHÔNG giống nhau trong yêu cầu GET và POST. Tôi đã xem xét các yêu cầu với Chrome Dev Tools và tôi đã thấy rằng phản hồi GET trả về tiêu đề Set-Cookie với cookie không hợp lệ (điều này khiến cho yêu cầu POST có cookie không hợp lệ và chuyển hướng trở lại trang đăng nhập) .

Điều này chỉ xảy ra trên các trang yêu cầu đăng nhập (và chuyển hướng đến trang đăng nhập nếu bạn chưa đăng nhập), nhưng tôi vẫn không thể tìm thấy lý do Flask gửi tiêu đề Set-Cookie với cookie không hợp lệ.

EDIT2: Sau một vài giờ, tôi đã phát hiện ra rằng việc xóa CSRF ẩn từ biểu mẫu trên các trang đó đã khắc phục sự cố cookie (yêu cầu GET không tạo Set-Cookie), do đó, nó phải có liên quan đến điều CSRF nhưng tôi không biết làm thế nào. Có bất kỳ hành vi đặc biệt nào đối với cookie phiên khi sử dụng CSRF mà tôi không tính đến?

Mẫu

"Mục mới":

{% 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 %}

Trình trang trí "Yêu cầu đăng nhập":

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
Điểm cuối

​​"Mục" (hoạt động như mong đợi):

@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)
Điểm cuối

​​"Mục mới" (trả về tiêu đề Set-Cookie có cookie không hợp lệ cho các yêu cầu 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))

Lỗi tôi gặp phải trong yêu cầu POST là như sau:

Value Error
Can't parse segment: \���
    
3
0 Câu trả lời                              0                         
nguồn đặt đây