I have a webPy app using sessions for user authentication. Sessions are initiated like so:
web.config.debug=Falsestore = web.session.DiskStore('/path_to_app/sessions')
if web.config.get('_session') is None:web.config.session_parameters['ignore_expiry'] = Falseweb.config.session_parameters['timeout'] = 600web.config.session_parameters['max_age'] = 600web.config.session_parameters['ignore_change_ip'] = Falseweb.config.session_parameters['expired_message'] = 'Session Expired... Please reload the page and login in again.'web.config.session_parameters['cookie_name'] = 'my_session_id'session_init = web.session.Session(app, store, initializer={'login':0, 'privilege':0, 'user':'none'})session = session_init._initializerweb.config._session = session
else:session = web.config._session
Here is the login class:
class Login:def GET(self):if logged() == True:return render.index()else:render = create_render(session['privilege'])return render.login()def POST(self):data= web.input()name = data['user']passwd = data['passwd']ident = model.get_users(m, name)try:if passwd == ident.password.strip():session['login'] = 1session['privilege'] = ident['privilege']session['user'] = namerender = create_render(session['privilege'])return render.index()else:session.login = 0session.privilege = 0session.user = 'none'render = create_render(session['privilege'])return render.login()except:session['login'] = 0session['privilege'] = 0render = create_render(session['privilege'])return render.login()
and here is the logged check:
def logged():if session['login']==1:return Trueelse:return False
I have two issues which I cannot figure out:
- When there are concurrent connections to the web server, they use the same session so if some one is logged in already, another used connecting to the site jumps straight in without authentication.
UPDATE:
A new session is in fact created in the disk store for each user but the details apart from the ID are the same - The issue still stands that a new user does not need to authenticate:
>>> x = base64.b64decode(open("/path_to_app/sessions/71b598e8a40c62cc6b5a1bf7a380d67886e87859").read())
>>> pickle.loads(x)
{'privilege': 2, 'ip': u'137.237.225.56', 'login': 1, 'user': u'admin', 'session_id': '71b598e8a40c62cc6b5a1bf7a380d67886e87859'}
>>>
>>> y = base64.b64decode(open("/path_to_app/sessions/5a7364dc2a23ea69c61212bc496500cbb15f89bd").read())
>>> pickle.loads(y)
{'privilege': 2, 'ip': u'137.237.225.133', 'login': 1, 'user': u'admin', 'session_id': '5a7364dc2a23ea69c61212bc496500cbb15f89bd'}
- When the session expires, it is not deleted. I can see the session expiring and producing the message as defined but if the user refreshes the page, they are straight back in again. Is there a way to kill the session when it expires?
Thanks!
I don't like to leave this hanging in case someone from the future discovers this and wants to know what I learned...
I ended up ditching the sessions in web.py and moved to Beaker Session Middleware using client side cookies only.
A quick example:
import web
from beaker.middleware import SessionMiddlewareurls = ('/', 'index','/login', 'Login','/logout', 'Logout')t_globals = {'datestr': web.datestr,'str': str,'datetime': datetime}# beaker options are optional.... but it's good to see
# where they are calledsession_opts = {'session.cookie_expires': True,'session.timeout' : 600,'session.secure' : True,
}# define webPy app
app = web.application(urls, globals())# smash it all together and define name for cookie key (sid)
def session_mw(app):return SessionMiddleware(app, config = session_opts, key = "sid")# function to check if we are logged in
def logged(session):if 'login' in session:if session['login']==1:return Trueelse:return Falseelse:return False# create different renders based on log in privilege
def create_render(privilege):session = web.ctx.environ['beaker.session']if logged(session) == True:if privilege == 0:render = web.template.render('/templates/user/', base='user_base', globals=t_globals)elif privilege == 1:render = web.template.render('/templates/user/', base='user_base', globals=t_globals)elif privilege == 2:render = web.template.render('/templates/admin/', base='base', globals=t_globals)else:render = web.template.render('/templates/viewer/', base='base', globals=t_globals)else:render = web.template.render('templates/', globals=t_globals)return renderclass Login:def GET(self):session = web.ctx.environ['beaker.session']if logged(session) == True:render = create_render(session['privilege'])return render.index()else:render = create_render(0)return render.login()# I get user credentials from a database (called in model.get_users) def POST(self):session = web.ctx.environ['beaker.session']data= web.input()name = data['user']passwd = data['passwd']ident = model.get_users(m, name)try:if passwd == ident.password.strip():session['login'] = 1session['privilege'] = ident['privilege']session['user'] = namesession.save()render = create_render(session['privilege'])return render.index()else:session.login = 0session.privilege = 0session.user = 'none'render = create_render(session['privilege'])return render.login()except:session['login'] = 0session['privilege'] = 0render = create_render(session['privilege'])return render.login()class Logout:def GET(self):session = web.ctx.environ['beaker.session']try:render = create_render(0)session.invalidate()session.delete()return render.logout()except:session.invalidate()session.delete()render = create_render(0)return render.logout()class index:def GET(self):session = web.ctx.environ['beaker.session']if logged(session) == False:raise web.seeother('/login')else:render = create_render(0)return render.index()if __name__ == "__main__":app.run(session_mw)