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