pallets-eco / flask-session Goto Github PK
View Code? Open in Web Editor NEWServer side session extension for Flask
Home Page: https://flask-session.readthedocs.io
License: BSD 3-Clause "New" or "Revised" License
Server side session extension for Flask
Home Page: https://flask-session.readthedocs.io
License: BSD 3-Clause "New" or "Revised" License
The use of self.db.create_all()
in SqlAlchemySessionInterface
is causing me some problems:
https://github.com/fengsp/flask-session/blob/master/flask_session/sessions.py#L458
When using two-step invocation, there is no guarantee of an app context available when session.init_app() is run. The call to db.create_all()
results in an error like:
RuntimeError: application not registered on db instance and no application bound to current context
Furthermore, I don't think it's the job of Flask-Session to call this method anyway. If the table needs to be created, IMO that needs to be handled by the application developer.
Suggestions:
db.create_all()
; orIf you decide on option 2 above, then IMO the call to db.create_all()
should still be replaced by code that only creates the session table. Based on these docs:
http://docs.sqlalchemy.org/en/latest/core/metadata.html
That would look something like the following for SqlAlchemySessionInterface.__init__()
:
class Session(self.db.model):
...
if create_session_table:
Session.table.create(db.engine)
I'd be happy to create a PR if you are interested.
Line 473 of
https://github.com/fengsp/flask-session/blob/master/flask_session/sessions.py
try:
sid = signer.unsign(sid)
except BadSignature:
sid = None
store_id = self.key_prefix + sid
If BadSignature, store_id fails with: "cannot concatenate 'str' and 'NoneType' objects"
This happens in all classes, not only this one
MongoDBSessionInterface
does not work on Python 3.x due to an exception being raised when the session is read back from MongoDB. This happens due to the str()
call in line 401 of sessions.py
in the current head (see https://github.com/fengsp/flask-session/blob/master/flask_session/sessions.py#L401), since type(document['val']) == bytes
, and casting it to a str
makes it unsuitable for pickle.loads
. Removing the call to str()
resolves the problem.
i go then error whenever set the key or not
app.secret_key = 'lfjsdlkfjdklsjfkl'
app.config['SESSION_USE_SIGNER'] = True
I'm attempting to run Flask-Session 0.1.1 under Python 2.6.6, and am running into an issue right around this line (and others, if I was using those session storage methods):
File "/var/www/appname/venv/lib/python2.6/site-packages/flask_session/sessions.py", line 118, in save_session
int(app.permanent_session_lifetime.total_seconds()))
AttributeError: 'datetime.timedelta' object has no attribute 'total_seconds'
It seems that datetime.timedelta.total_seconds
was added in Python 2.7.
Is there by chance a 2.6-compatible drop-in replacement you'd consider?
Thanks!
Setup: Flask 0.11, SQLAlchemy session interface, python 2.7.x
When using session.clear()
to empty a session, say on a logout signal to ensure an empty session record, the expiry
field is set to null in the database:
dev=# select session_id,expiry from sessions;
session_id | expiry
----------------------------------------------+--------
session:ed53619f-84d7-4985-9383-260aa9817125 |
(1 row)
This causes a TypeError exception on line 516:
if saved_session and saved_session.expiry <= datetime.utcnow():
# Delete expired session
self.db.session.delete(saved_session)
self.db.session.commit()
saved_session = None
Work-around solution is to check for saved_session.expiry
before comparison:
if saved_session and (not saved_session.expiry or saved_session.expiry <= datetime.utcnow()):
Unless I'm missing something, I don't see where this module exposes the necessary APIs to prevent vulnerabilities such as Session Fixation. In a scenario where you need a pre-authenticated session, how would one create a new session, move the contents of the old session over to the new session, remove the old session, and update the cookie to reflect the token for the new session? I realize I can use session.clear()
to remove the old session, but that is only 1/4 of the problem. Am I missing something? Or is that logic that has yet to be written?
I am using fakeredis as my Redis connection in my unit tests and it offers a decode_responses
argument which avoid returning bytes
:
>>> from fakeredis import FakeRedis
>>> rds_without, rds_with = FakeRedis(), FakeRedis(decode_responses=True))
>>> rds_without['a'] = 1
>>> rds_with['a'] = 1
>>> rds_without['a'], rds_with['a']
(b'1', '1')
>>> rds_with.keys()
['session:068678b2-4ecd-4747-91f4-624826d85447', 'a']
>>> rds_without.keys()
[b'session:068678b2-4ecd-4747-91f4-624826d85447', b'a']
As far as I can see in my tests your RedisSessionInterface doesn't support this argument and everything comes back as bytes? In fact, I can't do lookups without bytes
:
>>> session
<RedisSession {'_permanent': True, b'foo': b'bar'}>
>>> session['foo']
*** KeyError: 'foo'
Please see my initial report @ pallets/flask#2337 (comment)
I'm using flask-session
with MongoDB (with the help of Flask-PyMongo
).
Flask-PyMongo
uses timezone-aware datetime objects.
From its docs:
Flask-PyMongo always uses timezone-aware datetime objects. That is, it sets the tz_aware parameter to True when creating a connection. The timezone of datetime objects returned from MongoDB will always be UTC.
flask-session
, on the other hand, compares the expires
value in the document against datetime.utcnow()
which is not time zone aware.
Then the above exception is thrown:
TypeError: can't compare offset-naive and offset-aware datetimes
The workaround (that works for me) is to replace this line:
if document and document.get('expiration') <= datetime.utcnow():
with these two lines:
import pytz
if document and document.get('expiration') <= datetime.utcnow().replace(tzinfo=pytz.UTC):
A permanent solution may be to examine self.client.codec_options.tz_aware
(which is a boolean) and act accordingly.
flask == 0.12.2
Flask-PyMongo == 0.5.1
Flask-Session == 0.3.1
Basically what I want to do is to regenerate every session with some new set of keys without having users to log in again. How can I do this?
my entire app (from docs):
#!/usr/bin/env python
from flask import Flask, session
from flask.ext.session import Session
from flask import current_app
import pprint
app = Flask(__name__)
# Check Configuration section for more details
#SESSION_TYPE = 'redis'
app.config.from_object('cvms_flask.config')
Session(app)
@app.route('/set/')
def set():
pprint.pprint(current_app.config)
session['key'] = 'value'
return 'ok'
@app.route('/get/')
def get():
return session.get('key', 'not set')
if __name__ == '__main__':
app.run()
exception:
Traceback (most recent call last):
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/magregor/src/cisco/cvms/tests/testsession.py", line 16, in set
session['key'] = 'value'
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/werkzeug/local.py", line 341, in __setitem__
self._get_current_object()[key] = value
File "/Users/magregor/.virtualenvs/cvms/lib/python3.5/site-packages/flask/sessions.py", line 126, in _fail
raise RuntimeError('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.
however dumping current_app.config (right before attempting to use the session):
{ #snip
'RULES_LOGLEVEL': 'DEBUG',
'SECRET_KEY': '505<hash-snipped/>',
'SEND_FILE_MAX_AGE_DEFAULT': 43200,
'SERVER_NAME': None,
#snip }
I have implemented a FlaskSessionInterface for GAE's Datastore (NDB library): gaesession.py.
By reusing parts of my code, I can contribute with a GAE backend to this project. Would you like me to do so?
It seems that non-permanent sessions are being saved in the datastore.
For example, if SESSIONS_PERMANENT
config option is set to False
, Flask states that they should end when the browser is closed. However, in this plugin, the session is being saved to Redis (or whatever datastore you are using) with the default permanent session lifetime, whether the session is permanent or not. See: https://github.com/fengsp/flask-session/blob/master/flask_session/sessions.py#L166
Is this intended?
If not, I suggest that we add an if statement to check if the session is permanent before we save anything to a datastore.
We have come across an issue with this at my company, we will fork and raise a PR with our intended fix shortly...
I'm using Flask-Session and redis for an application im trying to make and im using gunicorn with 4 gevent workers as the production server.
I'm trying to build a counter which should have a seperate session id each time a new browser or tab is opened and each session id is supposed to maintain its own count.
Here's the code that i have till now.
from flask import Flask
import os
from flask.json import jsonify
from multiprocessing import Value
from flask import Flask, session
from flask_session import Session
import redis
import os
def create_app():
app = Flask(__name__)
app.secret_key = '123456789012345678901234'
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = redis.from_url('localhost:6379')
# app.config.from_object(__name__)
sess = Session()
sess.init_app(app)
@app.route('/set/')
def set():
session['key'] = 1
return 'ok'
@app.route('/get/')
def get():
session['key'] = session.get('key','not set') + 1
return 'Count: '+ str(session.get('key','not set')) + ', Process ID: ' +str(os.getpid())
return app
In the 'set' route, im setting the key value to 1 and whenever i go to 'get' the counter value increases.
I'm trying to figure out how to set session id for each new connection( new tab or browser) and then each session id holds it's count. Any help would be appreciated.
Please see my inline comment at 148b23a#commitcomment-10292407
I noticed there was a fix added for Python 3 to the way session string is handled but I'm still having problems.
data = self.serializer.loads(want_bytes(val))
When this line executes in open_session I'm still not getting my session back. I poked around I noticed pickle is raising exception of type _pickle.UnpicklingError
with no message to it.
Python 3.4.0
SQLAlchemy 0.9.8 + MySQL 5.5
Flask 0.10.1
I used session.clear()
with mongodb back-end
and delete cookie from client correctly but when user save cookie separately and send to server. I have session with this cookie.
How can solve this problem?
I spent the whole morning debugging an issue where submitting two requests in close proximity will cause a race condition in the flask-session extension.
I'm using the Redis session interface, but it might affect others as well.
Here is what happens:
session['my_list'].append('foo')
and session['my_list'].append('bar')
This is roughly what happens in Redis:
GET session:123 -> []
GET session:123 -> []
SETEX session:123 [foo]
SETEX session:123 [bar]
This is what should happen:
GET session:123 -> []
SETEX session:123 foo
GET session:123 -> [foo]
SETEX session:123 [foo, bar]
We have some extra logging code that makes use of the session in a ClosingIterator:
def setup_logging_middleware(self):
"""Add local variables we will use per request.
Right now we hang logging off of it.
"""
from werkzeug.wsgi import ClosingIterator
from werkzeug.local import release_local
def my_release_locals():
release_local(log_threadLocal)
def my_make_middleware(app):
"""Wrap a WSGI application so that cleaning up happens after request end."""
def application(environ, start_response):
return ClosingIterator(app(environ, start_response), my_release_locals)
return application
self.wsgi_app = my_make_middleware(self.wsgi_app)
Every once in a great while we see the following error pop up:
2017-04-27T11:33:37.187730+00:00 app[web.1]: Traceback (most recent call last):
2017-04-27T11:33:37.187732+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1182, in _execute_context
2017-04-27T11:33:37.187733+00:00 app[web.1]: context)
2017-04-27T11:33:37.187734+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 470, in do_execute
2017-04-27T11:33:37.187735+00:00 app[web.1]: cursor.execute(statement, parameters)
2017-04-27T11:33:37.187735+00:00 app[web.1]: psycopg2.IntegrityError: duplicate key value violates unique constraint "flask_session_session_id_key"
2017-04-27T11:33:37.187739+00:00 app[web.1]: DETAIL: Key (session_id)=(session:redacted-8e4b-481a-8788-redacted) already exists.
2017-04-27T11:33:37.187740+00:00 app[web.1]:
2017-04-27T11:33:37.187740+00:00 app[web.1]:
2017-04-27T11:33:37.187741+00:00 app[web.1]: The above exception was the direct cause of the following exception:
2017-04-27T11:33:37.187742+00:00 app[web.1]:
2017-04-27T11:33:37.187742+00:00 app[web.1]: Traceback (most recent call last):
2017-04-27T11:33:37.187743+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
2017-04-27T11:33:37.187743+00:00 app[web.1]: response = self.full_dispatch_request()
2017-04-27T11:33:37.187744+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/app.py", line 1615, in full_dispatch_request
2017-04-27T11:33:37.187745+00:00 app[web.1]: return self.finalize_request(rv)
2017-04-27T11:33:37.187745+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/app.py", line 1632, in finalize_request
2017-04-27T11:33:37.187746+00:00 app[web.1]: response = self.process_response(response)
2017-04-27T11:33:37.187747+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/app.py", line 1858, in process_response
2017-04-27T11:33:37.187748+00:00 app[web.1]: self.save_session(ctx.session, response)
2017-04-27T11:33:37.187749+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask/app.py", line 924, in save_session
2017-04-27T11:33:37.187749+00:00 app[web.1]: return self.session_interface.save_session(self, session, response)
2017-04-27T11:33:37.187750+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/flask_session/sessions.py", line 556, in save_session
2017-04-27T11:33:37.187751+00:00 app[web.1]: self.db.session.commit()
2017-04-27T11:33:37.187752+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/scoping.py", line 157, in do
2017-04-27T11:33:37.187752+00:00 app[web.1]: return getattr(self.registry(), name)(*args, **kwargs)
2017-04-27T11:33:37.187753+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 874, in commit
2017-04-27T11:33:37.187754+00:00 app[web.1]: self.transaction.commit()
2017-04-27T11:33:37.187755+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 461, in commit
2017-04-27T11:33:37.187755+00:00 app[web.1]: self._prepare_impl()
2017-04-27T11:33:37.187756+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 441, in _prepare_impl
2017-04-27T11:33:37.187757+00:00 app[web.1]: self.session.flush()
2017-04-27T11:33:37.187757+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 2139, in flush
2017-04-27T11:33:37.187758+00:00 app[web.1]: self._flush(objects)
2017-04-27T11:33:37.187758+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 2259, in _flush
2017-04-27T11:33:37.187759+00:00 app[web.1]: transaction.rollback(_capture_exception=True)
2017-04-27T11:33:37.187760+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 66, in __exit__
2017-04-27T11:33:37.187760+00:00 app[web.1]: compat.reraise(exc_type, exc_value, exc_tb)
2017-04-27T11:33:37.187761+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 187, in reraise
2017-04-27T11:33:37.187761+00:00 app[web.1]: raise value
2017-04-27T11:33:37.187762+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 2223, in _flush
2017-04-27T11:33:37.187763+00:00 app[web.1]: flush_context.execute()
2017-04-27T11:33:37.187763+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/unitofwork.py", line 389, in execute
2017-04-27T11:33:37.187764+00:00 app[web.1]: rec.execute(self)
2017-04-27T11:33:37.187765+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/unitofwork.py", line 548, in execute
2017-04-27T11:33:37.187765+00:00 app[web.1]: uow
2017-04-27T11:33:37.187766+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/persistence.py", line 181, in save_obj
2017-04-27T11:33:37.187767+00:00 app[web.1]: mapper, table, insert)
2017-04-27T11:33:37.187767+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/orm/persistence.py", line 835, in _emit_insert_statements
2017-04-27T11:33:37.187768+00:00 app[web.1]: execute(statement, params)
2017-04-27T11:33:37.187769+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 945, in execute
2017-04-27T11:33:37.187769+00:00 app[web.1]: return meth(self, multiparams, params)
2017-04-27T11:33:37.187770+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 263, in _execute_on_connection
2017-04-27T11:33:37.187770+00:00 app[web.1]: return connection._execute_clauseelement(self, multiparams, params)
2017-04-27T11:33:37.187771+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1053, in _execute_clauseelement
2017-04-27T11:33:37.187772+00:00 app[web.1]: compiled_sql, distilled_params
2017-04-27T11:33:37.187772+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1189, in _execute_context
2017-04-27T11:33:37.187773+00:00 app[web.1]: context)
2017-04-27T11:33:37.187778+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1402, in _handle_dbapi_exception
2017-04-27T11:33:37.187779+00:00 app[web.1]: exc_info
2017-04-27T11:33:37.187780+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 203, in raise_from_cause
2017-04-27T11:33:37.187780+00:00 app[web.1]: reraise(type(exception), exception, tb=exc_tb, cause=cause)
2017-04-27T11:33:37.187781+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 186, in reraise
2017-04-27T11:33:37.187781+00:00 app[web.1]: raise value.with_traceback(tb)
2017-04-27T11:33:37.187782+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1182, in _execute_context
2017-04-27T11:33:37.187783+00:00 app[web.1]: context)
2017-04-27T11:33:37.187784+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 470, in do_execute
2017-04-27T11:33:37.187784+00:00 app[web.1]: cursor.execute(statement, parameters)
2017-04-27T11:33:37.187786+00:00 app[web.1]: sqlalchemy.exc.IntegrityError: (psycopg2.IntegrityError) duplicate key value violates unique constraint "flask_session_session_id_key"
2017-04-27T11:33:37.187787+00:00 app[web.1]: DETAIL: Key (session_id)=(session:redacted-8e4b-481a-8788-redacted) already exists.
2017-04-27T11:33:37.187789+00:00 app[web.1]: [SQL: 'INSERT INTO flask_session (session_id, data, expiry) VALUES (%(session_id)s, %(data)s, %(expiry)s) RETURNING flask_session.id'] [parameters: {'session_id': 'session:redacted-8e4b-481a-8788-redacted', 'data': <psycopg2.extensions.Binary object at 0x7fb166e10120>, 'expiry': datetime.datetime(2017, 5, 28, 11, 33, 37, 174935)}]
FileSession not thread-safe if I use threaded parameter into creating Flask , look as:
app.run (threaded = True)
There are a large number in parallel,
data = self.cache.get (self.key_prefix + sid)
Will return None, but in the file session.py at line 320,
return self.session_class (sid = sid, permanent = self.permanent)
Ah, God, I always wondered why the session will be reset, Now I konw.
Allow DynamoDB as a session storage type.
...
self.store.delete({'id': store_id}) row-409 in session.py
...
self.store.delete({'id': store_id}) row-426 in session.py
....
I have changed to remove and everything goes well. (pymongo==3.2.2.)
If I configured my Flask session to use SQLAlchemy and signed cookies I end up with a Type Error when the first request hits my application.
This is the configuration I used to enable this functionality:
application.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:////tmp/test.db'"
application.secret_key = "some value"
application.config['SESSION_KEY_PREFIX'] = 'test'
application.config['SESSION_USE_SIGNER'] = True
application.config['SESSION_COOKIE_SECURE'] = True
application.config['SESSION_TYPE'] = 'sqlalchemy'
Session(application)
db = SQLAlchemy(application)
db.create_all()
The problem appears to originate from the itsdangerous library, the signer returns bytes string for use as the sid, this is concatenated to the key prefix (which is a unicode string) and results in the Type error (see screenshot). Also if I don't set the key prefix it fails as it tries to append None.
Using pickle is a major security flaw, and can be used for remote code execution or opening a shell.
I understand the pickled data doesn't get read from the client, but it's still a bad idea to store it in the database, since if the database server gets compromised, every single app server is compromised as well.
For more information, see: https://www.cs.uic.edu/~s/musings/pickle.html
This is create_app function:
import flask
from flask.ext.session import Session
from .models import db
sess = Session()
def create_app():
app = flask.Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SQLALCHEMY_ECHO'] = True
app.config['SESSION_SQLALCHEMY'] = db
app.config['SESSION_TYPE'] = 'sqlalchemy'
sess.init_app(app)
db.init_app(app)
with app.app_context():
db.create_all()
return app
Then exec this code:
app1 = create_app()
app2 = create_app()
An error occurred:
Traceback (most recent call last):
File "./runserver.py", line 12, in <module>
main()
File "./runserver.py", line 8, in main
app2 = create_app()
File "/home/computer/code/project/flownotebook/backend/flownotebook/__init__.py", line 18, in create_app
sess.init_app(app)
File "/usr/local/lib/python3.5/dist-packages/flask_session/__init__.py", line 61, in init_app
app.session_interface = self._get_interface(app)
File "/usr/local/lib/python3.5/dist-packages/flask_session/__init__.py", line 105, in _get_interface
config['SESSION_PERMANENT'])
File "/usr/local/lib/python3.5/dist-packages/flask_session/sessions.py", line 478, in __init__
class Session(self.db.Model):
File "/usr/local/lib/python3.5/dist-packages/flask_sqlalchemy/__init__.py", line 602, in __init__
DeclarativeMeta.__init__(self, name, bases, d)
File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/ext/declarative/api.py", line 64, in __init__
_as_declarative(cls, classname, cls.__dict__)
File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/ext/declarative/base.py", line 88, in _as_declarative
_MapperConfig.setup_mapping(cls, classname, dict_)
File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/ext/declarative/base.py", line 103, in setup_mapping
cfg_cls(cls_, classname, dict_)
File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/ext/declarative/base.py", line 131, in __init__
self._setup_table()
File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/ext/declarative/base.py", line 395, in _setup_table
**table_kw)
File "/usr/local/lib/python3.5/dist-packages/sqlalchemy/sql/schema.py", line 421, in __new__
"existing Table object." % key)
sqlalchemy.exc.InvalidRequestError: Table 'sessions' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object.
If I comment sess.init_app(app)
, this code works fine.
I guess that the two app instance shared the same database, repeat exec the function create_all(), my own definition of those tables can be created good, but the sessions table by using flask-session can not work in this situation.
I'm running flask-session with flask-login with the following versions:
The user gets authenticated via a user loader function and a few requests work well. But after maybe 3 to 5 page reloads, suddenly the user is logged out and subsequent requests are not authenticated.
In the session file, user_id still exists, but the other session values, like my custom session['server_token']
are getting cleared for some reason. Also, it always happens on an api request afaik to flask-restless. Eventually one request raises a ProcessingException when current_user.is_authenticated
is false and then subsequent requests fail.
For config settings I'm using this:
from datetime import timedelta
PERMANENT_SESSION_LIFETIME = timedelta(hours=8)
SESSION_TYPE = 'filesystem'
SESSION_PERMANENT = True
SESSION_KEY_PREFIX = 'gis'
SESSION_COOKIE_HTTPONLY = True
SESSION_USE_SIGNER = True
SESSION_COOKIE_SECURE = True if not DEBUG else False
I'd appreciate any direction someone might have for debugging this.
因为自己并不需要每一次请求的时候都更新 session 的有效期
#if not self.should_set_cookie(app, session):
# return
I'm using session with MongoDB and it fails because of a datetime error.
TypeError: can't compare offset-naive and offset-aware datetimes
File "/Library/Python/2.7/site-packages/flask/app.py", line 2000, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1984, in wsgi_app
ctx.push()
File "/Library/Python/2.7/site-packages/flask/ctx.py", line 332, in push
self.session = self.app.open_session(self.request)
File "/Library/Python/2.7/site-packages/flask/app.py", line 914, in open_session
return self.session_interface.open_session(self, request)
File "/Library/Python/2.7/site-packages/flask_session/sessions.py", line 411, in open_session
if document and document.get('expiration') <= datetime.utcnow():
TypeError: can't compare offset-naive and offset-aware datetimes
I had recently faced a similar issue while checking expiry of a token. Handled it with using a different datetime format.
I believe we need to use any other format like:
datetime.datetime.strptime(,"%d %b %Y %I:%M:%S %p")
Mongo Version : 3.4
Flask-Session==0.3.0
Every time a new request comes in the previous session values that i set is gone. I'm using SESSION_TYPE = 'filesystem'
and SESSION_PERMANENT = True
as well.
I'm using Free Heroku dyno for my chatbot.
To use json instead of pickle for serialize, you' d better set a redis instance like this:
from flask_session import Session, RedisSessionInterface
RedisSessionInterface.serializer = json
rds = redis.Redis(decode_responses=True) # make sure utf8
app.config['SESSION_REDIS'] = rds
Hi,
With Flask 0.11.1, I just upgraded from Flask-session 0.2.3 to 0.3.0.
It breaks login, not on my local machine, but on EB.
On my local machine: a request to /login_required_page redirects to /login, then redirects to /login_required_page.
On Elastic Beanstalk: a request to /login_required_page redirects to /login, then redirects to /login_required_page, then redirects to /login_reqired_page&next=login_required_page.
Logging in again causes the same error.
I am using flask-session for server-side sessions using Postgres.
From: http://flask.pocoo.org/docs/0.12/extensiondev/
As of Flask 0.11, most Flask extensions have transitioned to the new naming schema. The flask.ext.foo compatibility alias is still in Flask 0.11 but is now deprecated – you should use flask_foo.
Calls to .sign(session.sid)
fail with a TypeError in Python 3; .sign requires a bytes
value.
Simplest solution I see: at the top of the file, from itsdangerous import want_bytes
, and replace all instances of .sign(session.sid)
with .sign(want_bytes(session.sid))
.
Hello,
Do you have any examples for redis support? It seems to be not working and base on the code it doesn't connect to the settings specified (url, key) etc..
As I understand the documentation, the user's session should be deleted automatically (server-side) when the SESSION_PERMANENT option is enabled and the session has been idle longer than the PERMANENT_SESSION_LIFETIME value. However, in my application the session file is never removed when using the FileSystemSessionInterface.
from flask import Flask, session
from flask_session import Session, FileSystemSessionInterface
...
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SECRET_KEY'] = 'donthardcodethisvalue!'
app.config['SESSION_FILE_DIR'] = './my_sessions'
app.config['SESSION_USE_SIGNER'] = True
app.config['SESSION_FILE_MODE'] = 0644
app.config['PERMANENT_SESSION_LIFETIME'] = 30 #timout in seconds
app.config['SESSION_PERMANENT'] = True
#create and configure flask-session
sess = Session()
#bind app to flask-session
sess.init_app(app)
#define routes ...
However, the session is removed server-side as expected when using the Redis interface. Am I missing something with the FileSystemSessionInterface?
Additionally, looking at the source, it appears that the PERMANENT_SESSION_LIFETIME is never passed to some of the other interfaces such as MongoDB or SQLAlchemy. Is the session automatically expired server-side when using these interfaces?
I have a maximum of 30 or 50 users (the same users always) using my platform on any given day and I currently (after a couple weeks) have 90k+ entries in my SQLAlchemy table. What creates so many and why are they there, I believe I am using only default configurations.
I just noticed this behavior while using the Filesystem sessions of Flask-Session. On each new request, a new session file is written with a new key.
Take the following example application
from flask import Flask
from flask.ext.session import Session
app = Flask(__name__)
app.config["SECRET_KEY"] = "__replacewithsomethingunique__"
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
app.run(port=8001)
When I run this code and issue several curl requests, I receive a different session cookie header on each request.
$ curl -is localhost:8001 | grep Set-Cookie
Set-Cookie: session=2a2d9266-deaa-4412-82de-48193503534e; Expires=Mon, 12-Oct-2015 17:46:02 GMT; HttpOnly; Path=/
$ curl -is localhost:8001 | grep Set-Cookie
Set-Cookie: session=a98eebd4-909c-4c42-b68c-3cae7750e390; Expires=Mon, 12-Oct-2015 17:46:02 GMT; HttpOnly; Path=/
$ curl -is localhost:8001 | grep Set-Cookie
Set-Cookie: session=e547e8d2-54de-4359-a4a5-bcf206e88c1e; Expires=Mon, 12-Oct-2015 17:46:03 GMT; HttpOnly; Path=/
$ curl -is localhost:8001 | grep Set-Cookie
Set-Cookie: session=69e78241-5c2e-4bf4-936d-35931cb81e8c; Expires=Mon, 12-Oct-2015 17:46:03 GMT; HttpOnly; Path=/
After which the flask_session directory is filled with several session files
$ ls -1 flask_session/
113e38a76a00f2ebb4912fa547d75ec9
3184c223a385dd63ce728b9e8b778f5a
a62fce576b1734cc77fdd1302e815916
b242e7911524d66023836aaf9847b6fd
This differs from the default flask session behavior. By default flask does not send a Set-Cookie header if nothing happens to the session.
Obviously this could cause some trouble.
If you have more question about this issue or if there is something else I can do to help solving it please let me know.
In sessions.py, Class ServerSideSession, you set session.permanent = True by default, but flask set session.permanent = False by default.
Using SqlAlchemy (both with mysql and sqlite) if I set SESSION_PERMANENT to False the system return a TypeError
File "/home/draio/project/venv/lib/python2.7/site-packages/flask_session/sessions.py", line 516, in open_session
if saved_session and saved_session.expiry <= datetime.utcnow():
TypeError: can't compare datetime.datetime to NoneType
Changing the SESSION_TYPE in filesystem the system works and the cookie will be deleted when the browser is closed.
On the DB table the session row has the expiry row empty.
Expiry comes from expires variable tha is set on row 547:
expires = self.get_expiration_time(app, session)
get_expiration_time is a flask fuction that returns the expiration date for the session:
if session.permanent:
return datetime.utcnow() + app.permanent_session_lifetime
That's why the expiry field on sessions table is empty, a cookie set as non-permanent doesn't have a expiration date. So it's not possible for mysql and sqlite to check a NULL date.
To populate the expiry field in the DB table I changed:
expires = self.get_expiration_time(app, session)
into
expires = self.get_expiration_time(app, session) \
or datetime.utcnow() + app.permanent_session_lifetime
No more error but if i close the browser the ,session cookie is still there.
That's because the set_cookie function must have expires empty to delete the cookie when browser is closed.
So I changed:
expires = self.get_expiration_time(app, session)
into
expires = self.get_expiration_time(app, session) \
or datetime.utcnow() + app.permanent_session_lifetime
expires_cookie=expires if self.permanent else ''
And on line 561 I changed:
response.set_cookie(app.session_cookie_name, session_id,
expires=expires, httponly=httponly,
domain=domain, path=path, secure=secure)
into
response.set_cookie(app.session_cookie_name, session_id,
expires=expires_cookie, httponly=httponly,
domain=domain, path=path, secure=secure)
I hope that this could by helpful and clear.
UPDATE
Another way, more elegant, to solve the problem is to check self.permanent before checking if saved_session.expire is outdated.
On line 516 change
if saved_session and saved_session.expiry <= datetime.utcnow():
into something like
if self.permanent and saved_session and saved_session.expiry <= datetime.utcnow():
Also this solution works but, if I'm not wrong, in this way the session will never be deleted from the DB table and, more important, it will never be tested. That's could be a security problem.
In the other solution the expiration date is written to the DB. In that case the problem may be that for a time a cookie remains active even if on the browser has already been deleted. I do not know if this could be considered a security problem.
UPDATE IE11 issue
On IE11 you cannot have a Expires=;
, otherwise the cookie will never be stored.
For now I solved brutally with an if
on
if not saved_session:
if expires_cookie:
response.set_cookie(app.session_cookie_name, session_id,
expires=expires_cookie, httponly=httponly,
domain=domain, path=path, secure=secure)
else:
response.set_cookie(app.session_cookie_name, session_id,
httponly=httponly,
domain=domain, path=path, secure=secure)
Hi!
How could one handle exceptions with flask-session? When using SESSION_TYPE='redis' and redis is not available for some reason I can't find a way to catch the redis.exceptions.ConnectionError
exception.
Any ideas how to do this?
Thanks for this awesome extension!
Redis exceptions on open_session make Flask crash painfully, not popping the context correctly (leaking data across requests).
Flask doesn't catch any possible exceptions on the session_interface, resulting in messing up the context.
To reproduce
Fix
Ideally Flask uses its interfaces safely - always popping context. Bug created: pallets/flask#2517
Still, I think it would be nice that Flask-Session is safe as well, catching possible redis problems and not letting Flask deal with the exceptions.
Environment
Python version: 2.7.6
Flask version: 0.10.1
Werkzeug version: 0.11.11
Flask-Session: 0.3.1
I have a problem when I try to store some unicode data with the sqlalchemy interface.
This the error I had.
DataError: (psycopg2.DataError) invalid byte sequence for encoding "UTF8"
I think the type of the column data should be changed to LargeBinary
I'm using flask-sqlalchemy and sqlite file and when I create the database with typical db.create_all() all tables are created but sessions
What I'm missing?
Thanks!
We have a large app running on forked version of this project:
https://github.com/level12/flask-session/
I see there are a lot of open PRs. Are you interested in adding a contributor or two to this repo & PyPI so we can help with pull requests and releases?
Apparently setting
SESSION_REDIS = "/var/run/redis/redis.sock"
. . . does not produce magic.
File "/home/user/Projects/foo/venv/lib/python2.7/site-packages/flask_session/sessions.py", line 131, in open_session
val = self.redis.get(self.key_prefix + sid)
AttributeError: 'str' object has no attribute 'get'
Am I missing something obvious, or are you not supporting using a socket for redis sessions at this point?
http://flask.pocoo.org/extensions/
Any plans?
FileSession time is too short, I found in the File
self.cache = FileSystemCache (cache_dir, threshold = threshold, mode = mode)
Missing parameters default_timeout, because FileSystemCache default value is 300 seconds.
look at
class FileSystemCache(BaseCache):
"""
....
"""
#: used for temporary files by the FileSystemCache
_fs_transaction_suffix = '.__wz_cache'
def __init__(self, cache_dir, threshold=500, default_timeout=300, mode=0o600):
BaseCache.__init__(self, default_timeout)
self._path = cache_dir
self._threshold = threshold
self._mode = mode
So I think we should use Flask parameter "PERMANENT_SESSION_LIFETIME"
Hi I tried to clear the session, since I have no idea how to clear all session once logout, but after I did session.clear() I got this error
File "../env/lib/python2.7/site-packages/flask/app.py", line 2000, in __call__ return self.wsgi_app(environ, start_response) File "../env/lib/python2.7/site-packages/flask/app.py", line 1984, in wsgi_app ctx.push() File "../env/lib/python2.7/site-packages/flask/ctx.py", line 332, in push self.session = self.app.open_session(self.request) File "../env/lib/python2.7/site-packages/flask/app.py", line 914, in open_session return self.session_interface.open_session(self, request) File "../env/lib/python2.7/site-packages/flask_session/sessions.py", line 516, in open_session if saved_session and saved_session.expiry <= datetime.utcnow(): TypeError: can't compare datetime.datetime to NoneType
I tried to drop my session db table but still doesnt work
any idea @fengsp ?
Thanks
When no secret key is set the get_signer returns None but this is not catched.
2017-02-16 19:17:08,522 domogik.admin.application ERROR Request finalizing failed with an error while handling an error Traceback (most recent call last): File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1632, in finalize_request response = self.process_response(response) File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1858, in process_response self.save_session(ctx.session, response) File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 924, in save_session return self.session_interface.save_session(self, session, response) File "/usr/local/lib/python2.7/dist-packages/Flask_Session-0.3.0-py2.7.egg/flask_session/sessions.py", line 357, in save_session session_id = self._get_signer(app).sign(want_bytes(session.sid)) AttributeError: 'NoneType' object has no attribute 'sign'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.