2

Based on the example on GitHub, this is my Python script:

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)

This is the HTML template:

<!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>

Everything works fine. But the problem is user can use any HTML tags in the messages.

For example:

The example

I think it's little dangerous. Because any users can also run some JavaScript code and broadcast it. Then every clients will run it.

Is there's anyway can use Jinja auto escape the output, or there's any other ways?

4

2 回答 2

2

Flask-SocketIO 作者在这里。

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

但这一点很好,我已经更新了示例应用程序以正确处理用户输入。如何执行此操作取决于应用程序。对于这个例子,我选择在客户端使用 jQuery 进行转义:

$('#log').append('<br>' + $('<div/>').text('Received #' + msg.count + ': ' + msg.data).html());
于 2015-12-21T05:07:18.507 回答
1

但是,我发现的方法是,我们可以转义脚本中的 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.

演示输出:

除了输出

于 2015-12-20T04:02:00.327 回答