
From: ShaoHe Feng <shaohef@linux.vnet.ibm.com> When session timeout, come back to login page with an error message. When session logout, close session directly. Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com> --- src/kimchi/auth.py | 25 ++++++++++++++++++++++--- src/kimchi/config.py.in | 4 ++++ src/kimchi/server.py | 2 ++ ui/js/src/kimchi.main.js | 11 +++++++++-- ui/pages/login.html.tmpl | 2 ++ 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/kimchi/auth.py b/src/kimchi/auth.py index 9cb40d3..59889ed 100644 --- a/src/kimchi/auth.py +++ b/src/kimchi/auth.py @@ -161,7 +161,7 @@ def check_auth_session(): cherrypy.session.timeout * 60): cherrypy.session[USER_NAME] = None cherrypy.lib.sessions.expire() - raise cherrypy.HTTPError(401) + raise cherrypy.HTTPError(401, "sessionTimeout") else: cherrypy.session[REFRESH] = time.time() return True @@ -223,7 +223,7 @@ def logout(): cherrypy.session[USER_NAME] = None cherrypy.session[REFRESH] = 0 cherrypy.session.release_lock() - cherrypy.lib.sessions.expire() + cherrypy.lib.sessions.close() def has_permission(admin_methods): @@ -238,6 +238,7 @@ def has_permission(admin_methods): def kimchiauth(admin_methods=None): debug("Entering kimchiauth...") + session_missing = cherrypy.session.missing if check_auth_session(): if not has_permission(admin_methods): raise cherrypy.HTTPError(403) @@ -249,11 +250,29 @@ def kimchiauth(admin_methods=None): return # not a REST full request, redirect login page directly - if not template.can_accept('application/json'): + if ("Accept" in cherrypy.request.headers and + not template.can_accept('application/json')): redirect_login() + # from browser, and it stays on one page. + if session_missing and cherrypy.request.cookie.get("lastPage") is not None: + raise cherrypy.HTTPError(401, "sessionTimeout") + if not from_browser(): cherrypy.response.headers['WWW-Authenticate'] = 'Basic realm=kimchi' e = InvalidOperation('KCHAUTH0002E') raise cherrypy.HTTPError(401, e.message.encode('utf-8')) + + +def kimchisession(admin_methods=None): + session = cherrypy.request.cookie.get("kimchi") + last_page = cherrypy.request.cookie.get("lastPage") + headers = cherrypy.request.headers + authheader = headers.get('AUTHORIZATION') + # when client browser first login in, both the session and lastPage cookie + # are None. + # when session timeout, only session cookie is None. + if (session is None and last_page is None and authheader is None and + ("Accept" in headers and not template.can_accept('application/json'))): + redirect_login() diff --git a/src/kimchi/config.py.in b/src/kimchi/config.py.in index d4cbda0..f557516 100644 --- a/src/kimchi/config.py.in +++ b/src/kimchi/config.py.in @@ -179,6 +179,7 @@ class KimchiConfig(dict): 'tools.sessions.locking': 'explicit', 'tools.sessions.storage_type': 'ram', 'tools.sessions.timeout': SESSIONSTIMEOUT, + 'tools.kimchisession.on': True, 'tools.kimchiauth.on': False }, '/vnc_auto.html': { @@ -190,6 +191,9 @@ class KimchiConfig(dict): '/kimchi-ui.html': { 'tools.kimchiauth.on': True }, + '/login.html': { + 'tools.kimchisession.on': False, + }, '/data/screenshots': { 'tools.staticdir.on': True, 'tools.staticdir.dir': get_screenshot_path(), diff --git a/src/kimchi/server.py b/src/kimchi/server.py index 7344349..30140ce 100644 --- a/src/kimchi/server.py +++ b/src/kimchi/server.py @@ -77,6 +77,8 @@ def __init__(self, options): cherrypy.tools.nocache = cherrypy.Tool('on_end_resource', set_no_cache) cherrypy.tools.kimchiauth = cherrypy.Tool('before_handler', auth.kimchiauth) + cherrypy.tools.kimchisession = cherrypy.Tool('before_request_body', + auth.kimchisession) # Setting host to 127.0.0.1. This makes kimchi runs # as a localhost app, inaccessible to the outside # directly. You must go through the proxy. diff --git a/ui/js/src/kimchi.main.js b/ui/js/src/kimchi.main.js index 2a8f461..4dc57e5 100644 --- a/ui/js/src/kimchi.main.js +++ b/ui/js/src/kimchi.main.js @@ -138,7 +138,13 @@ kimchi.main = function() { */ var loadPage = function(url) { // Get the page content through Ajax and render it. - url && $('#main').load(url, function(responseText, textStatus, jqXHR) {}); + url && $('#main').load(url, function(responseText, textStatus, jqXHR) { + if (jqXHR['status'] === 401 || jqXHR['status'] === 303) { + var isSessionTimeout = jqXHR['responseText'].indexOf("sessionTimeout")!=-1; + document.location.href= isSessionTimeout ? 'login.html?error=sessionTimeout' : 'login.html'; + return; + } + }); }; /* @@ -223,11 +229,12 @@ kimchi.main = function() { } if (jqXHR['status'] === 401) { + var isSessionTimeout = jqXHR['responseText'].indexOf("sessionTimeout")!=-1; kimchi.user.showUser(false); kimchi.previousAjax = ajaxSettings; $(".empty-when-logged-off").empty(); $(".remove-when-logged-off").remove(); - document.location.href='login.html'; + document.location.href= isSessionTimeout ? 'login.html?error=sessionTimeout' : 'login.html'; return; } else if((jqXHR['status'] == 0) && ("error"==jqXHR.statusText)) { diff --git a/ui/pages/login.html.tmpl b/ui/pages/login.html.tmpl index 0e53041..1e80aad 100644 --- a/ui/pages/login.html.tmpl +++ b/ui/pages/login.html.tmpl @@ -74,6 +74,8 @@ function setMessage() { var err = "$getVar('data.error', '')"; if(err=="userPassWrong") document.getElementById("messUserPass").style.display = ""; + if(err=="sessionTimeout") + document.getElementById("messSession").style.display = ""; } function init() { setLang(); -- 1.9.3