<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">On 06/10/2014 09:27 PM, Aline Manera
wrote:<br>
</div>
<blockquote cite="mid:539707BD.2080807@linux.vnet.ibm.com"
type="cite">On 06/10/2014 09:42 AM, Sheldon wrote:
<br>
<blockquote type="cite">On 06/10/2014 02:11 AM, Aline Manera
wrote:
<br>
<blockquote 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"><shaohef@linux.vnet.ibm.com></a>
<br>
<br>
If the content type is application/json still raise 401
status code.
<br>
And let UI redirect to login page.
<br>
<br>
or the backe redirects to login page directly.
<br>
<br>
Signed-off-by: ShaoHe Feng
<a class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com"><shaohef@linux.vnet.ibm.com></a>
<br>
Signed-off-by: Yu Xin Huo
<a class="moz-txt-link-rfc2396E" href="mailto:huoyuxin@linux.vnet.ibm.com"><huoyuxin@linux.vnet.ibm.com></a>
<br>
---
<br>
src/kimchi/auth.py | 11 +++++++++++
<br>
src/kimchi/config.py.in | 3 +++
<br>
src/kimchi/root.py | 28 +++++++++++++++++++---------
<br>
ui/js/src/kimchi.main.js | 5 +----
<br>
4 files changed, 34 insertions(+), 13 deletions(-)
<br>
<br>
diff --git a/src/kimchi/auth.py b/src/kimchi/auth.py
<br>
index dc78ded..a38dbd3 100644
<br>
--- a/src/kimchi/auth.py
<br>
+++ b/src/kimchi/auth.py
<br>
@@ -28,6 +28,7 @@
<br>
import re
<br>
import termios
<br>
import time
<br>
+import urllib2
<br>
<br>
<br>
from kimchi import template
<br>
@@ -41,6 +42,12 @@
<br>
REFRESH = 'robot-refresh'
<br>
<br>
<br>
+def redirect_login():
<br>
+ next_url = urllib2.quote(
<br>
+ cherrypy.request.path_info.encode('utf-8'), safe="")
<br>
+ raise cherrypy.HTTPRedirect("/login.html?next=%s" %
next_url, 303)
<br>
+
<br>
+
<br>
def debug(msg):
<br>
pass
<br>
# cherrypy.log.error(msg)
<br>
@@ -234,6 +241,10 @@ def kimchiauth(admin_methods=None):
<br>
raise cherrypy.HTTPError(403)
<br>
return
<br>
<br>
+ # not a REST full request, redirect login page directly
<br>
+ if not template.can_accept('application/json'):
<br>
+ redirect_login()
<br>
+
<br>
if not from_browser():
<br>
cherrypy.response.headers['WWW-Authenticate'] = 'Basic
realm=kimchi'
<br>
<br>
diff --git a/src/kimchi/config.py.in
b/src/kimchi/config.py.in
<br>
index 0206570..d4cbda0 100644
<br>
--- a/src/kimchi/config.py.in
<br>
+++ b/src/kimchi/config.py.in
<br>
@@ -187,6 +187,9 @@ class KimchiConfig(dict):
<br>
'/spice.html': {
<br>
'tools.kimchiauth.on': True
<br>
},
<br>
+ '/kimchi-ui.html': {
<br>
+ 'tools.kimchiauth.on': True
<br>
+ },
<br>
'/data/screenshots': {
<br>
'tools.staticdir.on': True,
<br>
'tools.staticdir.dir': get_screenshot_path(),
<br>
diff --git a/src/kimchi/root.py b/src/kimchi/root.py
<br>
index 8b1d09b..181ab13 100644
<br>
--- a/src/kimchi/root.py
<br>
+++ b/src/kimchi/root.py
<br>
@@ -81,7 +81,7 @@ def get(self):
<br>
@cherrypy.expose
<br>
def default(self, page, **kwargs):
<br>
if page.endswith('.html'):
<br>
- return template.render(page, None)
<br>
+ return template.render(page, kwargs)
<br>
raise cherrypy.HTTPError(404)
<br>
<br>
@cherrypy.expose
<br>
@@ -110,14 +110,24 @@ def __init__(self, model, dev_env):
<br>
self.messages = messages
<br>
<br>
@cherrypy.expose
<br>
- def login(self, *args):
<br>
- params = parse_request()
<br>
- try:
<br>
- username = params['username']
<br>
- password = params['password']
<br>
- except KeyError, item:
<br>
- e = MissingParameter('KCHAUTH0003E', {'item': str(item)})
<br>
- raise cherrypy.HTTPError(400, e.message)
<br>
</blockquote>
<br>
<blockquote type="cite">+ def login(self, *args, **kwargs):
<br>
+ username = kwargs.get('username')
<br>
+ password = kwargs.get('password')
<br>
+ # forms base authentication
<br>
+ if username is not None:
<br>
+ # UI can pass the redirect url by "next" query parameter
<br>
+ next_url = kwargs.get('next', "/")
<br>
+ next_url = type(next_url) is list and next_url[0]
<br>
+ auth.login(username, password)
<br>
+ raise cherrypy.HTTPRedirect(next_url, 303)
<br>
+ else:
<br>
+ try:
<br>
+ params = parse_request()
<br>
+ username = params['username']
<br>
+ password = params['password']
<br>
+ except KeyError, item:
<br>
+ e = MissingParameter('KCHAUTH0003E', {'item': str(item)})
<br>
+ raise cherrypy.HTTPError(400, e.message)
<br>
</blockquote>
<br>
I didn't understand this code.
<br>
Why did you get username and password from kwargs and in
"else" from parse_request()?
<br>
Should that info be in a single location?
<br>
</blockquote>
parse_request() get the password and username from body for REST
API request.
<br>
for form authentication. The cherrypy will do it by itself, and
pass it to login
<br>
</blockquote>
<br>
And when in which situation we get the username and password from
kwargs?
<br>
<br>
PS. Sorry about too many questions but I am trying to understand
the code =)
<br>
</blockquote>
<br>
<div class="netInfoHeadersGroup netInfoRequestHeadersTitle "><span
class=" ">Request Headers</span><span
class="netHeadersViewSource request ">view source</span></div>
<table class=" " cellpadding="0" cellspacing="0">
<tbody role="list" aria-label="Request Headers"
class="netInfoRequestHeadersBody ">
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">Accept</span></td>
<td role="list" aria-label="Accept" class="netInfoParamValue "><code
aria-selected="true" tabindex="0" role="listitem"
class="focusRow subFocusRow a11yModified">text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">Accept-Encoding</span></td>
<td role="list" aria-label="Accept-Encoding"
class="netInfoParamValue "><code aria-selected="false"
tabindex="-1" role="listitem" class="focusRow subFocusRow
a11yModified">gzip, deflate</code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">Accept-Language</span></td>
<td role="list" aria-label="Accept-Language"
class="netInfoParamValue "><code role="listitem"
class="focusRow subFocusRow ">zh-cn,en-us;q=0.7,en;q=0.3</code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">Connection</span></td>
<td role="list" aria-label="Connection"
class="netInfoParamValue "><code role="listitem"
class="focusRow subFocusRow ">keep-alive</code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">Cookie</span></td>
<td role="list" aria-label="Cookie" class="netInfoParamValue "><code
role="listitem" class="focusRow subFocusRow ">userid=root;
kimchiLang=zh_CN; username=shhfeng; ticketVM=VqO6AWlH;
lastPage="/#tabs/templates"; kimchi</code><code
aria-selected="false" tabindex="-1" role="listitem"
class="focusRow subFocusRow a11yModified">=fc2fa059ee694c3d959fa1a1902557d21526e78e</code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">DNT</span></td>
<td role="list" aria-label="DNT" class="netInfoParamValue "><code
role="listitem" class="focusRow subFocusRow ">1</code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">Host</span></td>
<td role="list" aria-label="Host" class="netInfoParamValue "><code
role="listitem" class="focusRow subFocusRow ">localhost:8001</code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">Referer</span></td>
<td role="list" aria-label="Referer" class="netInfoParamValue
"><code role="listitem" class="focusRow subFocusRow "><a class="moz-txt-link-freetext" href="https://localhost:8001/login.html">https://localhost:8001/login.html</a></code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">User-Agent</span></td>
<td role="list" aria-label="User-Agent"
class="netInfoParamValue "><code role="listitem"
class="focusRow subFocusRow ">Mozilla/5.0 (X11; Linux
x86_64; rv:29.0) Gecko/20100101 Firefox/29.0</code></td>
</tr>
</tbody>
</table>
<table class=" " cellpadding="0" cellspacing="0">
<tbody role="list" aria-label="Response Headers From Cache"
class="netInfoCachedResponseHeadersBody ">
</tbody>
</table>
<div class="netInfoHeadersGroup netInfoPostRequestHeadersTitle "><span
class=" ">Request Headers From Upload Stream</span></div>
<table class=" " cellpadding="0" cellspacing="0">
<tbody role="list" aria-label="Request Headers From Upload Stream"
class="netInfoPostRequestHeadersBody ">
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">Content-Length</span></td>
<td role="list" aria-label="Content-Length"
class="netInfoParamValue "><code role="listitem"
class="focusRow subFocusRow ">41</code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">Content-Type</span></td>
<td role="list" aria-label="Content-Type"
class="netInfoParamValue "><code role="listitem"
class="focusRow subFocusRow ">application/x-www-form-urlencoded</code></td>
</tr>
</tbody>
</table>
<br>
<br>
post body. <br>
I think the cherrypy know <span class="netInfoPostContentType ">x-www-form-urlencoded,
it can parser the body by itself. </span> <br>
<br>
<table role="presentation" class="netInfoPostParamsTable "
cellpadding="0" cellspacing="0">
<tbody role="list" aria-label="Parameters" class=" ">
<tr role="presentation" class="netInfoPostParamsTitle ">
<td colspan="2" role="presentation" class=" ">
<div class="netInfoPostParams ">Parameters<span
class="netInfoPostContentType ">application/x-www-form-urlencoded</span></div>
</td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">next</span></td>
<td role="list" aria-label="next" class="netInfoParamValue "><code
aria-selected="false" tabindex="-1" role="listitem"
class="focusRow subFocusRow a11yModified">/</code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">password</span></td>
<td role="list" aria-label="password" class="netInfoParamValue
"><code role="listitem" class="focusRow subFocusRow ">123456</code></td>
</tr>
<tr role="listitem" class=" ">
<td role="presentation" class="netInfoParamName "><span
class=" ">username</span></td>
<td role="list" aria-label="username" class="netInfoParamValue
"><code aria-selected="false" tabindex="-1" role="listitem"
class="focusRow subFocusRow a11yModified">shhfeng</code></td>
</tr>
</tbody>
</table>
<table role="presentation" class="netInfoPostSourceTable "
cellpadding="0" cellspacing="0">
<tbody role="list" aria-label="Source" class=" ">
<tr role="presentation" class="netInfoPostSourceTitle ">
<td colspan="2" role="presentation" class=" ">
<div class="netInfoPostSource ">Source</div>
</td>
</tr>
<tr role="presentation" class=" ">
<td colspan="2" role="presentation" class=" "><code
aria-selected="true" tabindex="0" role="listitem"
class="focusRow subFocusRow a11yModified">next=%2F&username=shhfeng&password=123456</code></td>
</tr>
</tbody>
</table>
<br>
<br>
By our rest quest, the <span class=" ">Content-Type is
application/json</span> we paser it by ourself. <br>
<br>
<br>
<font color="#3333ff">I have check the cherrypy code: some
explanation for application/x-www-form-urlencoded</font><br>
<br>
def _get_body_params(self):<br>
warnings.warn(<br>
"body_params is deprecated in CherryPy 3.2, will be
removed in "<br>
"CherryPy 3.3.",<br>
DeprecationWarning<br>
)<br>
return self.body.params<br>
body_params = property(_get_body_params,<br>
doc= """<br>
If the request Content-Type is
'application/x-www-form-urlencoded' or<br>
multipart, this will be a dict of the params pulled from the
entity<br>
body; that is, it will be the portion of request.params that
come<br>
from the message body (sometimes called "POST params", although
they<br>
can be sent with various HTTP method verbs). This value is set
between<br>
the 'before_request_body' and 'before_handler' hooks (assuming
that<br>
process_request_body is True).<br>
<br>
Deprecated in 3.2, will be removed for 3.3 in favor of<br>
:attr:`request.body.params<cherrypy._cprequest.RequestBody.params>`.""")<br>
<br>
<br>
<blockquote cite="mid:539707BD.2080807@linux.vnet.ibm.com"
type="cite">
<blockquote type="cite">
<blockquote type="cite">
<br>
And if you raise/return, you don't need a "else" it eliminates
some indentation levels.
<br>
</blockquote>
I can remove the “else”
<br>
<blockquote type="cite">
<br>
<blockquote type="cite">try:
<br>
user_info = auth.login(username, password)
<br>
diff --git a/ui/js/src/kimchi.main.js
b/ui/js/src/kimchi.main.js
<br>
index 184029d..2a8f461 100644
<br>
--- a/ui/js/src/kimchi.main.js
<br>
+++ b/ui/js/src/kimchi.main.js
<br>
@@ -227,10 +227,7 @@ kimchi.main = function() {
<br>
kimchi.previousAjax = ajaxSettings;
<br>
$(".empty-when-logged-off").empty();
<br>
$(".remove-when-logged-off").remove();
<br>
- kimchi.window.open({
<br>
- url: 'login-window.html',
<br>
- id: 'login-window-wrapper'
<br>
- });
<br>
+ document.location.href='login.html';
<br>
return;
<br>
}
<br>
else if((jqXHR['status'] == 0) &&
("error"==jqXHR.statusText)) {
<br>
</blockquote>
<br>
<br>
<br>
</blockquote>
<br>
<br>
</blockquote>
<br>
<br>
<br>
</blockquote>
<br>
<br>
<pre class="moz-signature" cols="72">--
Thanks and best regards!
Sheldon Feng(冯少合)<a class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com"><shaohef@linux.vnet.ibm.com></a>
IBM Linux Technology Center</pre>
</body>
</html>