StuFish
StuFish

Reputation: 31

webPy Sessions - Concurrent users use same session and session timeout

I have a webPy app using sessions for user authentication. Sessions are initiated like so:

web.config.debug=False

store = web.session.DiskStore('/path_to_app/sessions')
if web.config.get('_session') is None:
    web.config.session_parameters['ignore_expiry'] = False
    web.config.session_parameters['timeout'] = 600
    web.config.session_parameters['max_age'] = 600
    web.config.session_parameters['ignore_change_ip'] = False
    web.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._initializer
    web.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'] = 1
                session['privilege'] = ident['privilege']
                session['user'] = name
                render = create_render(session['privilege'])
                return render.index()
            else:
                session.login = 0
                session.privilege = 0
                session.user = 'none'
                render = create_render(session['privilege'])
                return render.login()
        except:
            session['login'] = 0
            session['privilege'] = 0
            render = create_render(session['privilege'])
            return render.login()

and here is the logged check:

def logged():
    if session['login']==1:
        return True
    else:
        return False

I have two issues which I cannot figure out:

  1. 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'}
  1. 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!

Upvotes: 0

Views: 898

Answers (1)

StuFish
StuFish

Reputation: 31

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 SessionMiddleware

urls = (
         '/', '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 called

session_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 True
        else:
            return False
    else:
        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 render

class 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'] = 1
                    session['privilege'] = ident['privilege']
                    session['user'] = name
                    session.save()
                    render = create_render(session['privilege'])
                    return render.index()

                else:
                    session.login = 0
                    session.privilege = 0
                    session.user = 'none'
                    render = create_render(session['privilege'])
                    return render.login()
            except:
                session['login'] = 0
                session['privilege'] = 0
                render = 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)

Upvotes: 2

Related Questions