没有密钥...我想这是别的东西

No Secret Key... I imagine it was something else

我正在使用 Flask/Socketio/Javascript 制作一个聊天应用程序,当我设计“创建频道”功能时,当应用程序 运行 它说 RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret. .

我看过其他与“密钥”相关的主题,但首先:我没有将 secret_key 声明放在奇怪的地方,其次:我记得添加 app.config['SESSION_TYPE'],因为这是我上次绊倒的地方。

我认为问题与 flash 函数有关,因为当我删除它时,一切正常。有什么方法可以让我闪烁一条消息但不会收到错误消息吗?

我的代码: application.py

import os
import requests

from flask import Flask, jsonify, render_template, request, redirect, url_for, flash
from flask_socketio import SocketIO, emit, join_room, leave_room

app = Flask(__name__)
app.config["SECRET_KEY"] = os.getenv("SECRET_KEY")
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_PERMANENT']= False
socketio = SocketIO(app)
channels = {"1":0,"2":0,"3":0}

@app.route("/")
def home():
    return render_template('home.html', channels = channels)

@app.route("/chat")
def chat():
    username = request.args.get('username')
    channel_id = request.args.get("channel_id")
    if username and channel_id:
        channels[channel_id] +=1
        return render_template("index.html", username=username, channel_id=channel_id)
    print("Wait")
    return redirect(url_for('home'))

@app.route("/create")
def make_channel():
    channel_name = request.args.get("channel_name")
    if channel_name and not str.isspace(channel_name):
        channels[channel_name] = 0
        flash("Channel created!")
        return redirect(url_for('home'))
    flash('You have not filled in the channel name!')
    return render_template('home.html', channels=channels)

@socketio.on('join_room')
def join_room_event(data):
    app.logger.info("{} has joined channel {}. ".format(data['username'], data['channel']))
    join_room(data['channel'])
    socketio.emit('joined_room', data)

@socketio.on('leave_room')
def leave_room_event(data):
    app.logger.info("{} has left channel {}.".format(data['username'], data['channel']))
    leave_room(data['channel'])
    socketio.emit('left_room', data)
    channel_id = data['channel']
    channels[channel_id] -= 1


@socketio.on("send")
def vote(data):
    emit("announce message", data, broadcast=True)


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

home.html

<!DOCTYPE HTML>
<html>
    <head>
        <title>Hello, world!</title>
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
        {% if message != () %}
        <h4 class="text-danger">{{ message }}</h4>
        {% endif %}
        <form action="{{ url_for('chat') }}">
            <div>
                <label>Enter your name:</label>
                <label>
                    <input type="text" name="username">
                </label>
            </div>
            <div>
                <label>Enter Channel ID:</label>
                <select name="channel_id">
                    {% for channel in channels %}
                    <option value="{{ channel }}">{{ channel }} --- {{ channels[channel] }} users online</option>
                    {% endfor %}
                </select>
            </div>
            <button type="submit">Enter Room</button>
        </form>
        <form action="{{ url_for('make_channel') }}">
            <label>Enter Channel Name:</label>
            <label>
                <input type="text" name="channel_name">
            </label>
            <button type="submit">Create Channel</button>
        </form>
        <script>
            document.addEventListener('DOMContentLoaded')
        </script>
    </body>
</html>

index.html 注意:我知道我不应该将 javascript 和 HTML 放在同一个文件中,所以不要谈论那个。

<!DOCTYPE html>
<html lang="en">
    <head>
        <script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
        <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
        <script>
            document.addEventListener('DOMContentLoaded', () => {

                // Connect to websocket
                var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);

                socket.on('connect', () => {
                    socket.emit('join_room', {
                        'username': "{{ username }}",
                        'channel': '{{ channel_id }}'
                    })
                });

                // The button should emit the value of the textbox
                document.getElementById('send').onclick = e => {
                    e.preventDefault();
                    let message_input = document.getElementById('textbox');
                    const message = message_input.value.trim();
                    if(message.length){
                        socket.emit('send', {
                            'message': message,
                            'username': "{{ username }}",
                            'channel': "{{ channel_id }}"
                        });
                    }
                    message_input.value = '';
                    message_input.focus();

                };

                document.getElementById('leave').onclick = () =>{
                    const data = {
                        'username': '{{ username }}',
                        'channel': '{{ channel_id }}'
                    };
                    socket.emit('leave_room', data);
                    window.location.href = "{{ url_for('home') }}";

                };

                socket.on('left_room', data =>{
                    if (data.channel === "{{ channel_id }}"){
                        const inner = document.createElement('div');
                        inner.innerHTML = `<b>${data.username}</b> has left the room.`;
                        inner.style.backgroundColor = "#e1f3fb";
                        inner.style.fontFamily = "sans-serif";
                        inner.style.fontSize = "12px";
                        inner.style.borderColor = "#d5cec7";
                        inner.className = "rounded";
                        inner.style.display= "inline-block";
                        inner.style.border= '2px solid #d5cec7';
                        const div = document.createElement('div');
                        div.appendChild(inner);
                        div.style.width = "100%";
                        document.getElementById('message').appendChild(div);
                    }
                });


                socket.on('joined_room', data => {
                    if (data.channel === "{{ channel_id }}"){
                        const inner  = document.createElement('div');
                        if (data.username !== "{{ username }}"){
                            console.log('not me.');
                            inner.innerHTML = `<b>${data.username}</b> has joined the channel!`;
                        } else {
                            console.log('me.');
                            inner.innerHTML = `<b>You</b> joined the channel.`;
                        }
                        inner.style.backgroundColor = "#e1f3fb";
                        inner.style.fontFamily = "sans-serif";
                        inner.style.fontSize = "12px";
                        inner.style.borderColor = "#d5cec7";
                        inner.className = "rounded";
                        inner.style.display= "inline-block";
                        inner.style.border= '2px solid #d5cec7';
                        const div = document.createElement('div');
                        div.appendChild(inner);
                        div.style.width = "100%";
                        document.getElementById('message').appendChild(div);
                    }
                });

                socket.on('announce message', data => {
                    console.log(data.channel);
                    console.log("{{ channel_id }}");
                    if (data.channel === "{{ channel_id }}") {
                        const inner = document.createElement('div');
                        const div = document.createElement('div');
                        inner.innerHTML = `${data.username}: ${data.message}`;
                        inner.style.fontFamily = "sans-serif";
                        inner.style.fontSize = "12px";
                        inner.style.borderColor = "#d5cec7";
                        inner.className = "rounded";
                        inner.style.display = "inline-block";
                        inner.style.border = '2px solid #d5cec7';
                        if (data.username === "{{username}}") {
                            inner.style.backgroundColor = "#dcf8c7";
                            div.style.textAlign = "right";
                        } else {
                            inner.style.backgroundColor = "#ffffff";
                            div.style.textAlign = "left";
                        }
                        div.appendChild(inner);
                        div.style.width = "100%";
                        document.getElementById('message').appendChild(div);
                    }
                });
            });
        </script>
        <style>
           body{
                font-family: Arial, sans-serif;
           }
           div{
                padding: 2px 12px;
                text-align: center;
            }
        </style>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css">
        <title>Messages on Channel {{ channel_id }}</title>
    </head>
    <body>
        <h1>Welcome to Channel {{ channel_id }}</h1>
        <button id="leave">Leave Channel</button>
        <label for="textbox"></label><input id="textbox" placeholder="Message..." type="text">
        <button id="send">Send</button>
        <hr>
        <div id="message">
        </div>
    </body>
</html>

有人能帮忙吗? 错误信息:

127.0.0.1 - - [11/Jul/2020 14:22:35] "GET /create?channel_name=Hi HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/app.py", line 2464, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask_socketio/__init__.py", line 46, in __call__
    start_response)
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/engineio/middleware.py", line 74, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/app.py", line 2450, in wsgi_app
    response = self.handle_exception(e)
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/app.py", line 1867, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/scythia/Desktop/Project2/application.py", line 33, in make_channel
    flash("Channel created!")
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/helpers.py", line 423, in flash
    session["_flashes"] = flashes
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/werkzeug/local.py", line 350, in __setitem__
    self._get_current_object()[key] = value
  File "/Users/scythia/Desktop/Project2/venv/lib/python3.7/site-packages/flask/sessions.py", line 103, in _fail
    "The session is unavailable because no secret "
RuntimeError: The session is unavailable because no secret key was set.  Set the secret_key on the application to something unique and secret.

编辑

您是否尝试按照 Flask-SocketIO docs 中的说明将 app.run(debug=True) 更改为 socketio.run(app, debug=True)

from flask import Flask, render_template
from flask_socketio import SocketIO

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

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

未测试。



原回答

这是来自 Flask docs 的片段:

from flask import Flask, session, redirect, url_for, request
from markupsafe import escape

app = Flask(__name__)

# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

所以你应该把app.config["SECRET_KEY"] = os.getenv("SECRET_KEY")改成app.secret_key = os.getenv("SECRET_KEY").

https://flask-socketio.readthedocs.io/en/latest/#initialization

不需要改变你的code.In你的命令提示符,在设置环境(如果你正在使用)和其他东西之后,写这个; 设置 SECRET_KEY=你的密钥 在“您的密钥”的位置设置一些字符串作为您的密钥。

检查您是否安装了 python-dotenv,如果您的 .env 文件没有自动加载(使用 python-dotenv),您将永远无法获得具有 os.getenv() 功能的环境变量

在此之前,您可以手动设置app.secret_key = 'xxx'看看是否是我上面提到的问题。