10

I'm running a Flask application with Gunicorn as a web server. The whole project is deployed to Heroku.

Procfile

web: gunicorn app:app --log-file=-

Flask sessions are implemented server side, only a session id is stored in the flask.session object. Whenever I'm trying to do a login, I get logged in correctly at first, but then get redirected to the starting site (which should be the user site).

LoginController.py

def login(form) :
    User.session.set(User.getByLogin(form))
    if User.session.exists() :
        return redirect(Urls.home)
    return redirect(Urls.login)

The log shows that User.session.exists() returns True but in the next method (during the redirect)...

HomeController.py

def view() :
    if User.session.exists() :
        return CourseController.view()
    return render_template("home.html")

...the same method returns False.

User.session object

def exists(self) :
    key = session.get("user_key")
    user = self.users.get(key)
    Log.debug("session::exists", user = user)
    return user is not None

In all following requests the user is randomly logged in or not.

What can be the reason for this? I heard that a too large session object can result in data loss, but I'm only storing integers in it.

redevined
  • 772
  • 2
  • 6
  • 23
  • 3
    When gunicorn runs with more than one worker, the session is not shared between the two workers. When user login with the first worker, the user session is with that worker only. When user tries for another request it goes to other worker where it will not get user details and it will ask you to login again. We are also facing the same issue. I looked into the gunicorn but didn't get any fine solution. – Jyoti Amage Feb 05 '19 at 05:51
  • Same problem here ("For some reason the dict where I stored my sessions in was sometimes empty and sometimes not"). Did any of you find a solution? – Parzival Feb 22 '19 at 13:54

4 Answers4

23

Looks like there were two problems:

  • The app.secret_key shouldn't be set to os.urandom(24) because every worker will have another secret key
  • For some reason the dict where I stored my sessions in was sometimes empty and sometimes not... Still haven't found the reason for this though

Storing the sessions in a database instead a dictionary at runtime solves the problem.

redevined
  • 772
  • 2
  • 6
  • 23
0

I had a similar issue, but for me the answer was related to the cookies. A new session was being created when I opened my development environment, then another one when going to google, and a new one after a successful log in.

The problem was that my SESSION_COOKIE_DOMAIN was incorrect, and the cookie domain was being set to a different host. For my local development purposes I set SESSION_COOKIE_DOMAIN = '127.0.0.1', and use http://127.0.0.1: to access it, and it works OK now.

Emilio
  • 2,526
  • 22
  • 26
0

I had the same issue, while working locally worked, but on the server nothing did.

Found out when I changed 'app.secret_key' from a "my_secret_key" to os.urandom(24) with one my test user Was always in the session, with the other was never set in the session. reading several pages i did try adding a name to the cookie

app.config['SECRET_KEY'] = os.urandom(24)
# this is important or wont work
app.config['SESSION_COOKIE_NAME'] = "my_session"

now it works as is expected and i can log in, go to other webpages, and log out will remove the keys from the session.

pelos
  • 1,744
  • 4
  • 24
  • 34
0

For everyone who come across this problem, I am going to provide a different point of view:

it may have nothing to do with gunicorn's multi-workers!

First thing to do, make sure you use flask's session right. Don't define the session variable in global! Instead, define it under the view function. Otherwise, it would be just a regular variable named "session" and shared between different client rather than a flask's session variable created separate for different client.

If you are doing it right (use filesystem to check: app.config["SESSION_TYPE"] = "filesystem"), there should be a file created for each client under a flask_session folder to store you session variable (make sure you use multiple browsers or devices to check), therefore, even with gunicorn's multi-workers, the session variable would still persist.