<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">On 06/10/2014 02:22 AM, Aline Manera
      wrote:<br>
    </div>
    <blockquote cite="mid:5395FB56.2050404@linux.vnet.ibm.com"
      type="cite">On 06/05/2014 01:10 PM, <a class="moz-txt-link-abbreviated" href="mailto:shaohef@linux.vnet.ibm.com">shaohef@linux.vnet.ibm.com</a>
      wrote:
      <br>
      <blockquote type="cite">From: ShaoHe Feng
        <a class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>
        <br>
        <br>
        When session timeout, come back to login page with an
        <br>
        error message.
        <br>
        <br>
        When session logout, close session directly.
        <br>
        <br>
        Signed-off-by: ShaoHe Feng <a class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>
        <br>
        ---
        <br>
        &nbsp; src/kimchi/auth.py&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | 21 +++++++++++++++++++--
        <br>
        &nbsp; src/kimchi/config.py.in&nbsp; |&nbsp; 4 ++++
        <br>
        &nbsp; src/kimchi/server.py&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp; 2 ++
        <br>
        &nbsp; ui/js/src/kimchi.main.js |&nbsp; 3 ++-
        <br>
        &nbsp; ui/pages/login.html.tmpl |&nbsp; 2 ++
        <br>
        &nbsp; 5 files changed, 29 insertions(+), 3 deletions(-)
        <br>
        <br>
        diff --git a/src/kimchi/auth.py b/src/kimchi/auth.py
        <br>
        index 9cb40d3..dcdd74a 100644
        <br>
        --- a/src/kimchi/auth.py
        <br>
        +++ b/src/kimchi/auth.py
        <br>
        @@ -161,7 +161,7 @@ def check_auth_session():
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.session.timeout * 60):
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.session[USER_NAME] = None
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.lib.sessions.expire()
        <br>
        -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise cherrypy.HTTPError(401)
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise cherrypy.HTTPError(401, "sessionTimeout")
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.session[REFRESH] = time.time()
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return True
        <br>
        @@ -223,7 +223,7 @@ def logout():
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.session[USER_NAME] = None
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.session[REFRESH] = 0
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.session.release_lock()
        <br>
        -&nbsp;&nbsp;&nbsp; cherrypy.lib.sessions.expire()
        <br>
        +&nbsp;&nbsp;&nbsp; cherrypy.lib.sessions.close()
        <br>
        <br>
        <br>
        &nbsp; def has_permission(admin_methods):
        <br>
        @@ -238,6 +238,7 @@ def has_permission(admin_methods):
        <br>
        <br>
        &nbsp; def kimchiauth(admin_methods=None):
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; debug("Entering kimchiauth...")
        <br>
        +&nbsp;&nbsp;&nbsp; session_missing = cherrypy.session.missing
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if check_auth_session():
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not has_permission(admin_methods):
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise cherrypy.HTTPError(403)
        <br>
        @@ -252,8 +253,24 @@ def kimchiauth(admin_methods=None):
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not template.can_accept('application/json'):
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; redirect_login()
        <br>
      </blockquote>
      <br>
      <br>
      <blockquote type="cite">+&nbsp;&nbsp;&nbsp; # from browser, and it stays on one
        page.
        <br>
        +&nbsp;&nbsp;&nbsp; if session_missing and
        cherrypy.request.cookie.get("lastPage") is not None:
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise cherrypy.HTTPError(401, "sessionTimeout")
        <br>
        +
        <br>
      </blockquote>
      <br>
      Why is it needed?
      <br>
      The session timeout is handled in check_auth_session() which
      already return cherrypy.HTTPError(401, "sessionTimeout")
      <br>
      <br>
    </blockquote>
    here is the difference between kimchi and lastPage cookie.<br>
    kimchi cookie set expires. but lastPage does set it. <br>
    also we set lastPage only for browser.&nbsp; not for REST Full request. <br>
    <br>
    when session timeout, cherrypy will clean session data. <br>
    <font color="#3333ff">check_auth_session</font> will check session
    data. no session date may means session timeout or http base
    authentication. <br>
    &nbsp;<br>
    <br>
    <br>
    Here is the session cookie ID and lastPage cookie. <br>
    <table class=" " cellpadding="0" cellspacing="0">
      <tbody role="list" aria-label="Response Headers"
        class="netInfoResponseHeadersBody ">
        <tr role="listitem" class=" ">
          <td role="presentation" class="netInfoParamName "><span
              class=" ">Server</span></td>
          <td role="list" aria-label="Server" class="netInfoParamValue "><code
              aria-selected="false" tabindex="-1" role="listitem"
              class="focusRow subFocusRow a11yModified">nginx/1.4.7</code></td>
        </tr>
        <tr role="listitem" class=" ">
          <td role="presentation" class="netInfoParamName "><span
              class=" ">Set-Cookie</span></td>
          <td role="list" aria-label="Set-Cookie"
            class="netInfoParamValue "><code aria-selected="true"
              tabindex="0" role="listitem" class="focusRow subFocusRow
              a11yModified">kimchi=02fff0323dbe0bfbffb6f377e48ac5d9802de890;
              expires=Wed, 11 Jun 2014 03:33:34 GMT; httponly; Path</code><code
              aria-selected="false" tabindex="-1" role="listitem"
              class="focusRow subFocusRow a11yModified">=/; secure
            </code><code aria-selected="false" tabindex="-1"
              role="listitem" class="focusRow subFocusRow a11yModified">lastPage="/#tabs/templates";
              Path=/</code></td>
        </tr>
        <tr role="listitem" class=" ">
          <td role="presentation" class="netInfoParamName "><span
              class=" ">Strict-Transport-Security</span></td>
          <td role="list" aria-label="Strict-Transport-Security"
            class="netInfoParamValue "><code role="listitem"
              class="focusRow subFocusRow ">max-age=31536000;
              includeSubdomains;</code></td>
        </tr>
      </tbody>
    </table>
    <br>
    <blockquote cite="mid:5395FB56.2050404@linux.vnet.ibm.com"
      type="cite">
      <br>
      <br>
      <blockquote type="cite">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not from_browser():
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.response.headers['WWW-Authenticate'] = 'Basic
        realm=kimchi'
        <br>
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e = InvalidOperation('KCHAUTH0002E')
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise cherrypy.HTTPError(401, e.message.encode('utf-8'))
        <br>
        +
        <br>
        +
        <br>
        +def kimchisession(admin_methods=None):
        <br>
        +&nbsp;&nbsp;&nbsp; session = cherrypy.request.cookie.get("kimchi")
        <br>
        +&nbsp;&nbsp;&nbsp; last_page = cherrypy.request.cookie.get("lastPage")
        <br>
        +&nbsp;&nbsp;&nbsp; # when client browser first login in, both the session and
        lastPage cookie
        <br>
        +&nbsp;&nbsp;&nbsp; # are None.
        <br>
        +&nbsp;&nbsp;&nbsp; # when session timeout, only session cookie is None.
        <br>
        +&nbsp;&nbsp;&nbsp; if (session is None and last_page is None and
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template.can_accept('text/html')):
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if last_page is None:
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; redirect_login()
        <br>
        diff --git a/src/kimchi/config.py.in b/src/kimchi/config.py.in
        <br>
        index d4cbda0..f557516 100644
        <br>
        --- a/src/kimchi/config.py.in
        <br>
        +++ b/src/kimchi/config.py.in
        <br>
        @@ -179,6 +179,7 @@ class KimchiConfig(dict):
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'tools.sessions.locking': 'explicit',
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'tools.sessions.storage_type': 'ram',
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'tools.sessions.timeout': SESSIONSTIMEOUT,
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'tools.kimchisession.on': True,
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'tools.kimchiauth.on': False
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '/vnc_auto.html': {
        <br>
        @@ -190,6 +191,9 @@ class KimchiConfig(dict):
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '/kimchi-ui.html': {
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'tools.kimchiauth.on': True
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '/login.html': {
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'tools.kimchisession.on': False,
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '/data/screenshots': {
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'tools.staticdir.on': True,
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'tools.staticdir.dir': get_screenshot_path(),
        <br>
        diff --git a/src/kimchi/server.py b/src/kimchi/server.py
        <br>
        index 7344349..30140ce 100644
        <br>
        --- a/src/kimchi/server.py
        <br>
        +++ b/src/kimchi/server.py
        <br>
        @@ -77,6 +77,8 @@ def __init__(self, options):
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.tools.nocache =
        cherrypy.Tool('on_end_resource', set_no_cache)
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.tools.kimchiauth =
        cherrypy.Tool('before_handler',
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        auth.kimchiauth)
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cherrypy.tools.kimchisession =
        cherrypy.Tool('before_request_body',
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        auth.kimchisession)
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Setting host to 127.0.0.1. This makes kimchi runs
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # as a localhost app, inaccessible to the outside
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # directly. You must go through the proxy.
        <br>
        diff --git a/ui/js/src/kimchi.main.js b/ui/js/src/kimchi.main.js
        <br>
        index 2a8f461..78971f8 100644
        <br>
        --- a/ui/js/src/kimchi.main.js
        <br>
        +++ b/ui/js/src/kimchi.main.js
        <br>
        @@ -223,11 +223,12 @@ kimchi.main = function() {
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
        <br>
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (jqXHR['status'] === 401) {
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var isSessionTimeout =
        jqXHR['responseText'].indexOf("sessionTimeout")!=-1;
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kimchi.user.showUser(false);
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kimchi.previousAjax = ajaxSettings;
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(".empty-when-logged-off").empty();
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(".remove-when-logged-off").remove();
        <br>
        -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.location.href='login.html';
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.location.href= isSessionTimeout ?
        'login.html/?error=sessionTimeout' : 'login.html';
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if((jqXHR['status'] == 0) &amp;&amp;
        ("error"==jqXHR.statusText)) {
        <br>
        diff --git a/ui/pages/login.html.tmpl b/ui/pages/login.html.tmpl
        <br>
        index fc6cee6..4a7c87e 100644
        <br>
        --- a/ui/pages/login.html.tmpl
        <br>
        +++ b/ui/pages/login.html.tmpl
        <br>
        @@ -185,6 +185,8 @@ function setMessage() {
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var err = "$getVar('data.error', '')";
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(err=="userPassWrong")
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.getElementById("messUserPass").style.display
        = "";
        <br>
        +&nbsp;&nbsp;&nbsp; if(err=="sessionTimeout")
        <br>
        +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.getElementById("messSession").style.display =
        "";
        <br>
        &nbsp; }
        <br>
        &nbsp; function init() {
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setLang();
        <br>
      </blockquote>
      <br>
      <br>
      <br>
    </blockquote>
    <br>
    <br>
    <pre class="moz-signature" cols="72">-- 
Thanks and best regards!

Sheldon Feng(&#20911;&#23569;&#21512;)<a class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>
IBM Linux Technology Center</pre>
  </body>
</html>