Reputation: 11691
I want to save an ID between requests, using Flask session
cookie, but I'm getting an Internal Server Error
as result, when I perform a request.
I prototyped a simple Flask app for demonstrating my problem:
#!/usr/bin/env python
from flask import Flask, session
app = Flask(__name__)
@app.route('/')
def run():
session['tmp'] = 43
return '43'
if __name__ == '__main__':
app.run()
Why I can't store the session
cookie with the following value when I perform the request?
Upvotes: 34
Views: 54061
Reputation: 10005
As @falsetru mentioned, you have to set a secret key.
Before sending the session
cookie to the user's browser, Flask signs the cookies cryptographically, and that doesn't mean that you cannot decode the cookie. I presume that Flask keeps track of the signed cookies, so it can perform it's own 'magic', in order to determine if the cookie that was sent along with the request (request headers), is a valid cookie or not.
Some methods that you may use, all related with Flask class instance, generally defined as app
:
defining the secret_key
variable for app
object
app.secret_key = b'6hc/_gsh,./;2ZZx3c6_s,1//'
using the config()
method
app.config['SECRET_KEY'] = b'6hc/_gsh,./;2ZZx3c6_s,1//'
using an external configuration file for the entire Flask application
$ grep pyfile app.py
app.config.from_pyfile('flask_settings.cfg')
$ cat flask_settings.py
SECRET_KEY = b'6hc/_gsh,./;2ZZx3c6_s,1//'
Here's an example (an adaptation from this article), focused on providing a more clearer picture of Flask session
cookie, considering the participation of both Client and Server sides:
from flask import Flask, request, session
import os
app = Flask(__name__)
@app.route('/')
def f_index():
# Request Headers, sent on every request
print("\n\n\n[Client-side]\n", request.headers)
if 'visits' in session:
# getting value from session dict (Server-side) and incrementing by 1
session['visits'] = session.get('visits') + 1
else:
# first visit, generates the key/value pair {"visits":1}
session['visits'] = 1
# 'session' cookie tracked from every request sent
print("[Server-side]\n", session)
return "Total visits:{0}".format(session.get('visits'))
if __name__ == "__main__":
app.secret_key = os.urandom(24)
app.run()
Here's the output:
$ python3 sessions.py
* Serving Flask app "sessions" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
[Client-side]
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: keep-alive
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
[Server-side]
<SecureCookieSession {'visits': 1}>
127.0.0.1 - - [12/Oct/2018 14:27:05] "GET / HTTP/1.1" 200 -
[Client-side]
Upgrade-Insecure-Requests: 1
Cookie: session=eyJ2aXNpdHMiOjF9.DqKHCQ.MSZ7J-Zicehb6rr8qw43dCVXVNA # <--- session cookie
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: keep-alive
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
[Server-side]
<SecureCookieSession {'visits': 2}>
127.0.0.1 - - [12/Oct/2018 14:27:14] "GET / HTTP/1.1" 200 -
You may have noticed that in the example above, I'm using the os
lib and the urandom()
function, in order to generate Flask's secret key, right?
From the official doc:
How to generate good secret keys
A secret key should be as random as possible. Your operating system has ways to generate pretty random data based on a cryptographic random generator. Use the following command to quickly generate a value for Flask.secret_key (or SECRET_KEY):
$ python -c 'import os; print(os.urandom(16))'
b'_5#y2L"F4Q8z\n\xec]/'
PLUS NOTE
As you can see, the creators of Flask support the practice of using
os.urandom()
for building the Flask secret key, from older versions of the tool to its latest version. So: why @joshlsullivan's answer received downvotes (deserves an upvote) and why @MikhailKashkin writes that, usingos.urandom()
is terrible idea, are mysteries.
Upvotes: 1
Reputation: 1500
Under app = Flask(__name__)
place this: app.secret_key = os.urandom(24)
.
Upvotes: 0
Reputation: 368894
According to Flask sessions documentation:
... What this means is that the user could look at the contents of your cookie but not modify it, unless they know the secret key used for signing.
In order to use sessions you have to set a secret key.
Set secret key. And you should return string, not int.
#!/usr/bin/env python
from flask import Flask, session
app = Flask(__name__)
@app.route('/')
def run():
session['tmp'] = 43
return '43'
if __name__ == '__main__':
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
app.run()
Upvotes: 51