【问题标题】:How to escape HTML characters in Flask-SocketIO?如何在 Flask-SocketIO 中转义 HTML 字符?
【发布时间】:2015-12-20 03:57:59
【问题描述】:

基于 GitHub 上的示例,这是我的 Python 脚本:

from flask import Flask, render_template, session, request
from flask_socketio import SocketIO, emit

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, async_mode='eventlet')


@app.route('/')
def index():
    return render_template('index.html')


@socketio.on('my event', namespace='/test')
def test_message(message):
    session['receive_count'] = session.get('receive_count', 0) + 1
    emit('my response',
         {'data': message['data'], 'count': session['receive_count']})

if __name__ == '__main__':
    socketio.run(app, debug=True)

这是 HTML 模板:

<!DOCTYPE HTML>
<html>
<head>
    <script src="//code.jquery.com/jquery-1.4.2.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script>

    <script charset="utf-8">
        $(document).ready(function(){
            namespace = '/test'; // change to an empty string to use the global namespace

            // the socket.io documentation recommends sending an explicit package upon connection
            // this is specially important when using the global namespace
            var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);

            // event handler for server sent data
            // the data is displayed in the "Received" section of the page
            socket.on('my response', function(msg) {
                $('#log').append('<br>Received #' + msg.count + ': ' + msg.data);
            });

            // handlers for the different forms in the page
            // these send data to the server in a variety of ways
            $('form#emit').submit(function(event) {
                socket.emit('my event', {data: $('#emit_data').val()});
                return false;
            });
        });
    </script>
</head>
<body>  
    <form id="emit" method="POST" action='#'>
        <input type="text" name="emit_data" id="emit_data" placeholder="Message">
        <input type="submit" value="Echo">
    </form>

    <h2>Receive:</h2>
    <div id="log"></div>
</body>
</html>

一切正常。但问题是用户可以在消息中使用 任何 HTML 标签

例如:

我认为这有点危险。因为任何用户也可以运行一些 JavaScript 代码并广播它。然后每个客户端都会运行它。

有没有什么办法可以使用 Jinja 自动转义输出,或者还有其他方法吗?

【问题讨论】:

  • 示例应用程序旨在作为如何发送和接收消息的快速示例,而不是作为如何安全处理用户输入的示例。但这一点很好,我将更新示例以正确处理用户输入。为这项工作添加了一个问题:github.com/miguelgrinberg/Flask-SocketIO/issues/185
  • @Miguel:哇,太酷了。但是我建议发布答案而不是评论,我会接受它。
  • 我正在使用 python 3.7 并且我的消息没有使用上面的代码显示。知道为什么这没有打印出预期的结果吗?

标签: python flask escaping flask-socketio


【解决方案1】:

Flask-SocketIO 作者在这里。

示例应用程序旨在作为如何发送和接收消息的快速示例,我不认为它是如何安全处理用户输入的示例。

但重点是正确的,我现在更新了example app 以正确处理用户输入。如何执行此操作取决于应用程序。对于这个例子,我选择在客户端使用 jQuery 进行转义:

$('#log').append('<br>' + $('<div/>').text('Received #' + msg.count + ': ' + msg.data).html());

【讨论】:

    【解决方案2】:

    但是,我发现的方法是,我们可以像这样转义脚本中的 HTML 字符:

    import jinja2
    
    # other code here
    
    @socketio.on('my event', namespace='/test')
    def test_message(message):
        session['receive_count'] = session.get('receive_count', 0) + 1
        emit('my response',
             {'data': jinja2.escape(message['data']), 'count': session['receive_count']})
    #                 ^^^^^^^^^^^^^^ use jinja2 escape the output before send it to the clients.
    

    演示输出:

    【讨论】:

    • 但无论如何,我仍在寻找一种可以转义模板中的 HTML 字符的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 2015-06-10
    • 2010-11-16
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多