使用 Flask 中的会话传递变量时出现键错误

Posted

技术标签:

【中文标题】使用 Flask 中的会话传递变量时出现键错误【英文标题】:Key Error when passing a variable using session in Flask 【发布时间】:2018-11-17 19:30:48 【问题描述】:

我想使用 session 将变量从函数传递到 Flask 应用程序中的类。这是我的代码:

@app.route('/login', methods=['POST'])
def login():
    if not request.is_json:
        return jsonify("msg": "Missing JSON in request"), 400

    username = request.json.get('username', None)
    password = request.json.get('password', None)
    session['client_fname'] = request.json.get('Client First Name', None)
    session['client_lname'] = request.json.get('Client Last Name', None)

    ... ...

    access_token = create_access_token(identity=username)
    return jsonify(access_token=access_token), 200

class PrivateResource(Resource):
    @app.route('/protected', methods=['GET'])
    @jwt_required

    def sendData():
        return mysqldb.addUser("".format(session['client_fname']),"".format(session['client_lname']))

我要传递的变量是session['client_fname']session['client_lname']。但是,当我尝试使用 curl -X GET http://localhost:5000/protected -H "Authorization: Bearer JWTGOESHERE" 触发 sendData() 时,我得到:

  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask/app.py", line 2309, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask/app.py", line 2295, in wsgi_app
    response = self.handle_exception(e)
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask_restful/__init__.py", line 273, in error_router
    return original_handler(e)
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask/app.py", line 1741, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask_restful/__init__.py", line 273, in error_router
    return original_handler(e)
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask_jwt_extended/view_decorators.py", line 101, in wrapper
    return fn(*args, **kwargs)
  File "/Users/open/PycharmProjects/FlaskMiddleware/Flask-API-Middleware-V1/authenticate.py", line 48, in sendData
    return mysqldb.addUser("".format(session['client_fname'],None),"".format(session['client_lname']))
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/werkzeug/local.py", line 377, in <lambda>
    __getitem__ = lambda x, i: x._get_current_object()[i]
  File "/Users/open/venv/FlaskMiddleware/lib/python2.7/site-packages/flask/sessions.py", line 83, in __getitem__
    return super(SecureCookieSession, self).__getitem__(key)
KeyError: 'client_fname'

我使用session 传递变量的方式有什么问题?我该如何解决这个问题?

更新

如果这是与保留会话有关的 cookie 问题,我该如何实现?现在我在curl -H "Content-Type: application/json" -X POST -d '"username":"user1","password":"abc123","Client First Name":"SAUR","Client Last Name":"KRIS"' http://localhost:5000/login -c cookies.txt 中创建一个cookie 文件,然后尝试curl -X GET http://localhost:5000/protected -H "Authorization: Bearer JWTGOESHERE" -b cookies.txt。现在我收到TypeError: The view function did not return a valid response. The function either returned None or ended without a return statement.,我不确定这是进步还是完全错误。

【问题讨论】:

您是否在客户端跟踪会话 cookie? 想必你之前也通过 curl 调用过login。你在做些什么来在 curl 调用中保留你的会话? @DanielRoseman 我是正确的。保留会话是指拥有某种 cookie 文件的文件路径吗? 是的,您的会话似乎没有保留。您可以尝试通过使用requests.session() 来使用python requests 库,而不是直接使用cURL。 Look here 获取我在类似情况下如何使用它的示例。 你用的是什么扩展?我假设 flask_jwt_extended 因为 create_access_token 功能,但我宁愿确定。 【参考方案1】:

您似乎正在使用flask_jwt_extended,因此您可以通过将该数据直接存储在令牌中来绕过该问题。

# ...
access_token = create_access_token(
  'first_name': request.json.get('Client First Name', None),
  'last_name': request.json.get('Client Last Name', None)
)

然后在protected 路由中检索它:

# ...
user_adata = get_jwt_identity()

【讨论】:

【参考方案2】:

您几乎肯定不会在请求之间保留状态。如果您使用的是 postman 或 curl,请确保保存 session id cookie。如果您使用requests,请使用requests.session()

【讨论】:

我一直在谷歌搜索如何在 curl 中实现这一点。我必须编辑我的烧瓶代码还是通过 curl 命令完成,例如curl --cookie "session=&lt;encoded session&gt;" 像他们在这里一样使用curl --cookie-jar jar.txt . . .:coderwall.com/p/iy3iqw/… 即。 curl http://url.com/login --cookie-jar cookies.txt &amp;&amp; curl http://url.com/protected --cookie cookies.txt 使用邮递员这是一个非常好的工具来进行这种测试,我也猜这是一个状态问题【参考方案3】:

您的更新看起来很可能正在取得进展,但 mysqldb.addUser 函数可能返回 None。

确定您是否正在取得进展的最简单方法是在return mysqldb.addUser("".format(session['client_fname']),"".format(session['client_lname'])) 行处使用断点进行调试(我通常使用 PyCharm,但大多数 IDE 都会有一些用于调试的东西,或者您可以使用 pdb) .一个更快但更混乱的选项,在调用 mysqldb.addUser 之前添加一个 print 语句,然后在打印返回值之后再添加一个 print 语句。

【讨论】:

以上是关于使用 Flask 中的会话传递变量时出现键错误的主要内容,如果未能解决你的问题,请参考以下文章

[mysql-connector-python在将表作为参数传递时,在表名周围添加单引号。表名来自Flask会话变量

如何在 jinja 2 - Flask 中访问会话变量

使用 Python、Flask、HTML 时出现 NSException 错误

在宏中传递变量 args 时出现语法错误

Flask:当我尝试访问索引时出现错误 404

使用 elasticbeanstalk 部署 Flask 时出现 AWS mod_wsgi 错误