webPy 会话 - 并发用户使用相同的会话和会话超时
webPy Sessions - Concurrent users use same session and session timeout
我有一个使用会话进行用户身份验证的 webPy 应用程序。会话是这样启动的:
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
这是登录名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()
这是记录的检查:
def logged():
if session['login']==1:
return True
else:
return False
我有两个问题无法解决:
- 当有与 Web 服务器的并发连接时,它们使用相同的会话,因此如果有人已经登录,另一个使用连接到该站点的人会直接跳入而无需身份验证。
更新:
实际上在磁盘存储中为每个用户创建了一个新会话,但除了 ID 之外的详细信息是相同的 - 问题仍然存在,即新用户不需要进行身份验证:
>>> 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'}
- 当会话过期时,它不会被删除。我可以看到会话过期并生成定义的消息,但如果用户刷新页面,他们会再次直接返回。有没有办法在会话到期时终止会话?
谢谢!
我不想让这个悬而未决,以防未来的某个人发现这个并想知道我学到了什么...
我最终放弃了 web.py 中的会话,转而使用仅使用客户端 cookie 的 Beaker 会话中间件。
一个简单的例子:
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)
我有一个使用会话进行用户身份验证的 webPy 应用程序。会话是这样启动的:
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
这是登录名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()
这是记录的检查:
def logged():
if session['login']==1:
return True
else:
return False
我有两个问题无法解决:
- 当有与 Web 服务器的并发连接时,它们使用相同的会话,因此如果有人已经登录,另一个使用连接到该站点的人会直接跳入而无需身份验证。
更新:
实际上在磁盘存储中为每个用户创建了一个新会话,但除了 ID 之外的详细信息是相同的 - 问题仍然存在,即新用户不需要进行身份验证:
>>> 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'}
- 当会话过期时,它不会被删除。我可以看到会话过期并生成定义的消息,但如果用户刷新页面,他们会再次直接返回。有没有办法在会话到期时终止会话?
谢谢!
我不想让这个悬而未决,以防未来的某个人发现这个并想知道我学到了什么...
我最终放弃了 web.py 中的会话,转而使用仅使用客户端 cookie 的 Beaker 会话中间件。
一个简单的例子:
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)