Workaround for UiPassword cookie issues with sandboxed iframes
This commit is contained in:
parent
439f8fc476
commit
36d96d484e
1 changed files with 53 additions and 12 deletions
|
@ -14,6 +14,7 @@ plugin_dir = os.path.dirname(__file__)
|
|||
|
||||
if "sessions" not in locals().keys(): # To keep sessions between module reloads
|
||||
sessions = {}
|
||||
whitelisted_client_ids = {}
|
||||
|
||||
|
||||
def showPasswordAdvice(password):
|
||||
|
@ -28,8 +29,26 @@ def showPasswordAdvice(password):
|
|||
@PluginManager.registerTo("UiRequest")
|
||||
class UiRequestPlugin(object):
|
||||
sessions = sessions
|
||||
whitelisted_client_ids = whitelisted_client_ids
|
||||
last_cleanup = time.time()
|
||||
|
||||
def getClientId(self):
|
||||
return self.env["REMOTE_ADDR"] + " - " + self.env["HTTP_USER_AGENT"]
|
||||
|
||||
def whitelistClientId(self, session_id=None):
|
||||
if not session_id:
|
||||
session_id = self.getCookies().get("session_id")
|
||||
client_id = self.getClientId()
|
||||
if client_id in self.whitelisted_client_ids:
|
||||
self.whitelisted_client_ids[client_id]["updated"] = time.time()
|
||||
return False
|
||||
|
||||
self.whitelisted_client_ids[client_id] = {
|
||||
"added": time.time(),
|
||||
"updated": time.time(),
|
||||
"session_id": session_id
|
||||
}
|
||||
|
||||
def route(self, path):
|
||||
# Restict Ui access by ip
|
||||
if config.ui_restrict and self.env['REMOTE_ADDR'] not in config.ui_restrict:
|
||||
|
@ -42,10 +61,22 @@ class UiRequestPlugin(object):
|
|||
self.cleanup()
|
||||
# Validate session
|
||||
session_id = self.getCookies().get("session_id")
|
||||
if session_id not in self.sessions: # Invalid session id, display login
|
||||
if session_id not in self.sessions and self.getClientId() not in self.whitelisted_client_ids:
|
||||
# Invalid session id and not whitelisted ip: display login
|
||||
return self.actionLogin()
|
||||
return super(UiRequestPlugin, self).route(path)
|
||||
|
||||
def actionWrapper(self, path, *args, **kwargs):
|
||||
if config.ui_password and self.isWrapperNecessary(path):
|
||||
session_id = self.getCookies().get("session_id")
|
||||
if session_id not in self.sessions:
|
||||
# We only accept cookie based auth on wrapper
|
||||
return self.actionLogin()
|
||||
else:
|
||||
self.whitelistClientId()
|
||||
|
||||
return super().actionWrapper(path, *args, **kwargs)
|
||||
|
||||
# Action: Login
|
||||
@helper.encodeResponse
|
||||
def actionLogin(self):
|
||||
|
@ -53,13 +84,14 @@ class UiRequestPlugin(object):
|
|||
self.sendHeader()
|
||||
posted = self.getPosted()
|
||||
if posted: # Validate http posted data
|
||||
if self.checkPassword(posted.get("password")):
|
||||
if self.sessionCheckPassword(posted.get("password")):
|
||||
# Valid password, create session
|
||||
session_id = self.randomString(26)
|
||||
self.sessions[session_id] = {
|
||||
"added": time.time(),
|
||||
"keep": posted.get("keep")
|
||||
}
|
||||
self.whitelistClientId(session_id)
|
||||
|
||||
# Redirect to homepage or referer
|
||||
url = self.env.get("HTTP_REFERER", "")
|
||||
|
@ -74,20 +106,26 @@ class UiRequestPlugin(object):
|
|||
template = template.replace("{result}", "bad_password")
|
||||
yield template
|
||||
|
||||
def checkPassword(self, password):
|
||||
return password == config.ui_password
|
||||
|
||||
def randomString(self, nchars):
|
||||
return ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(nchars))
|
||||
|
||||
@classmethod
|
||||
def cleanup(cls):
|
||||
cls.last_cleanup = time.time()
|
||||
for session_id, session in list(cls.sessions.items()):
|
||||
def sessionCheckPassword(self, password):
|
||||
return password == config.ui_password
|
||||
|
||||
def sessionDelete(self, session_id):
|
||||
del self.sessions[session_id]
|
||||
|
||||
for client_id in list(self.whitelisted_client_ids):
|
||||
if self.whitelisted_client_ids[client_id]["session_id"] == session_id:
|
||||
del self.whitelisted_client_ids[client_id]
|
||||
|
||||
def sessionCleanup(self):
|
||||
self.last_cleanup = time.time()
|
||||
for session_id, session in list(self.sessions.items()):
|
||||
if session["keep"] and time.time() - session["added"] > 60 * 60 * 24 * 60: # Max 60days for keep sessions
|
||||
del(cls.sessions[session_id])
|
||||
self.sessionDelete(session_id)
|
||||
elif not session["keep"] and time.time() - session["added"] > 60 * 60 * 24: # Max 24h for non-keep sessions
|
||||
del(cls.sessions[session_id])
|
||||
self.sessionDelete(session_id)
|
||||
|
||||
# Action: Display sessions
|
||||
@helper.encodeResponse
|
||||
|
@ -95,6 +133,8 @@ class UiRequestPlugin(object):
|
|||
self.sendHeader()
|
||||
yield "<pre>"
|
||||
yield json.dumps(self.sessions, indent=4)
|
||||
yield "\r\n"
|
||||
yield json.dumps(self.whitelisted_client_ids, indent=4)
|
||||
|
||||
# Action: Logout
|
||||
@helper.encodeResponse
|
||||
|
@ -103,7 +143,8 @@ class UiRequestPlugin(object):
|
|||
session_id = self.getCookies().get("session_id")
|
||||
if not self.env.get("HTTP_REFERER") or session_id == self.get.get("session_id"):
|
||||
if session_id in self.sessions:
|
||||
del self.sessions[session_id]
|
||||
self.sessionDelete(session_id)
|
||||
|
||||
self.start_response('301 Redirect', [
|
||||
('Location', "/"),
|
||||
('Set-Cookie', "session_id=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT")
|
||||
|
|
Loading…
Reference in a new issue