From: ShaoHe Feng <shaohef(a)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(a)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 583efd4..b3e69d4 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