Merge pull request #3353 from InspectorCaracal/webclient-uid

Add a unique ID to each webclient instance
This commit is contained in:
Griatch 2023-12-20 22:46:27 +01:00 committed by GitHub
commit 833fe5a543
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 20 deletions

View file

@ -68,7 +68,7 @@ class WebSocketClient(WebSocketServerProtocol, _BASE_SESSION_CLASS):
""" """
try: try:
# client will connect with wsurl?csessid&browserid # client will connect with wsurl?csessid&page_id&browserid
webarg = self.http_request_uri.split("?", 1)[1] webarg = self.http_request_uri.split("?", 1)[1]
except IndexError: except IndexError:
# this may happen for custom webclients not caring for the # this may happen for custom webclients not caring for the
@ -82,9 +82,12 @@ class WebSocketClient(WebSocketServerProtocol, _BASE_SESSION_CLASS):
logger.log_trace(str(self)) logger.log_trace(str(self))
return None return None
self.csessid, *browserstr = webarg.split("&", 1) self.csessid, *cargs = webarg.split("&", 2)
if browserstr: if len(cargs) == 1:
self.browserstr = str(browserstr[0]) self.browserstr = str(cargs[0])
elif len(cargs) == 2:
self.page_id = str(cargs[0])
self.browserstr = str(cargs[1])
if self.csessid: if self.csessid:
return _CLIENT_SESSIONS(session_key=self.csessid) return _CLIENT_SESSIONS(session_key=self.csessid)

View file

@ -270,6 +270,18 @@ class AjaxWebClient(resource.Resource):
""" """
return html.escape(request.args[b"csessid"][0].decode("utf-8")) return html.escape(request.args[b"csessid"][0].decode("utf-8"))
def get_client_page_id(self, request):
"""
Helper to get the client page id out of the request.
Args:
request (Request): Incoming request object.
Returns:
csessid (int): The client-page id.
"""
return html.escape(request.args[b"cuid"][0].decode("utf-8"))
def get_browserstr(self, request): def get_browserstr(self, request):
""" """
Get browser-string out of the request. Get browser-string out of the request.
@ -313,10 +325,10 @@ class AjaxWebClient(resource.Resource):
def client_disconnect(self, csessid): def client_disconnect(self, csessid):
""" """
Disconnect session with given csessid. Disconnect session with given id.
Args: Args:
csessid (int): Session id. csessid (int): Client page+session id.
""" """
if csessid in self.requests: if csessid in self.requests:
@ -334,7 +346,8 @@ class AjaxWebClient(resource.Resource):
request (Request): Incoming request. request (Request): Incoming request.
""" """
csessid = self.get_client_sessid(request) session_id = self.get_client_sessid(request)
page_id = self.get_client_page_id(request)
browserstr = self.get_browserstr(request) browserstr = self.get_browserstr(request)
remote_addr = ip_from_request(request) remote_addr = ip_from_request(request)
@ -349,9 +362,9 @@ class AjaxWebClient(resource.Resource):
sess.client = self sess.client = self
sess.init_session("ajax/comet", remote_addr, self.sessionhandler) sess.init_session("ajax/comet", remote_addr, self.sessionhandler)
sess.csessid = csessid sess.csessid = session_id+page_id
sess.browserstr = browserstr sess.browserstr = browserstr
csession = _CLIENT_SESSIONS(session_key=sess.csessid) csession = _CLIENT_SESSIONS(session_key=session_id)
uid = csession and csession.get("webclient_authenticated_uid", False) uid = csession and csession.get("webclient_authenticated_uid", False)
if uid: if uid:
# the client session is already logged in # the client session is already logged in
@ -359,7 +372,7 @@ class AjaxWebClient(resource.Resource):
sess.logged_in = True sess.logged_in = True
# watch for dead links # watch for dead links
self.last_alive[csessid] = (time.time(), False) self.last_alive[sess.csessid] = (time.time(), False)
if not self.keep_alive: if not self.keep_alive:
# the keepalive is not running; start it. # the keepalive is not running; start it.
self.keep_alive = LoopingCall(self._keepalive) self.keep_alive = LoopingCall(self._keepalive)
@ -373,7 +386,7 @@ class AjaxWebClient(resource.Resource):
# actually do the connection # actually do the connection
sess.sessionhandler.connect(sess) sess.sessionhandler.connect(sess)
return jsonify({"msg": host_string, "csessid": csessid}) return jsonify({"msg": host_string, "csessid": session_id})
def mode_keepalive(self, request): def mode_keepalive(self, request):
""" """
@ -384,7 +397,7 @@ class AjaxWebClient(resource.Resource):
request (Request): Incoming request. request (Request): Incoming request.
""" """
csessid = self.get_client_sessid(request) csessid = self.get_client_sessid(request) + self.get_client_page_id(request)
self.last_alive[csessid] = (time.time(), False) self.last_alive[csessid] = (time.time(), False)
return b'""' return b'""'
@ -397,7 +410,7 @@ class AjaxWebClient(resource.Resource):
request (Request): Incoming request. request (Request): Incoming request.
""" """
csessid = self.get_client_sessid(request) csessid = self.get_client_sessid(request) + self.get_client_page_id(request)
self.last_alive[csessid] = (time.time(), False) self.last_alive[csessid] = (time.time(), False)
cmdarray = json.loads(request.args.get(b"data")[0]) cmdarray = json.loads(request.args.get(b"data")[0])
for sess in self.sessionhandler.sessions_from_csessid(csessid): for sess in self.sessionhandler.sessions_from_csessid(csessid):
@ -415,7 +428,7 @@ class AjaxWebClient(resource.Resource):
request (Request): Incoming request. request (Request): Incoming request.
""" """
csessid = html.escape(request.args[b"csessid"][0].decode("utf-8")) csessid = self.get_client_sessid(request) + self.get_client_page_id(request)
self.last_alive[csessid] = (time.time(), False) self.last_alive[csessid] = (time.time(), False)
dataentries = self.databuffer.get(csessid) dataentries = self.databuffer.get(csessid)
@ -441,7 +454,7 @@ class AjaxWebClient(resource.Resource):
request (Request): Incoming request. request (Request): Incoming request.
""" """
csessid = self.get_client_sessid(request) csessid = self.get_client_sessid(request) + self.get_client_page_id(request)
try: try:
sess = self.sessionhandler.sessions_from_csessid(csessid)[0] sess = self.sessionhandler.sessions_from_csessid(csessid)[0]
sess.sessionhandler.disconnect(sess) sess.sessionhandler.disconnect(sess)

View file

@ -220,6 +220,7 @@ An "emitter" object must have a function
var websocket = null; var websocket = null;
var wsurl = window.wsurl; var wsurl = window.wsurl;
var csessid = window.csessid; var csessid = window.csessid;
var cuid = window.cuid;
var connect = function() { var connect = function() {
if (websocket && websocket.readyState != websocket.CLOSED) { if (websocket && websocket.readyState != websocket.CLOSED) {
@ -227,7 +228,7 @@ An "emitter" object must have a function
return; return;
} }
// Important - we pass csessid tacked on the url // Important - we pass csessid tacked on the url
websocket = new WebSocket(wsurl + '?' + csessid + '&' + browser); websocket = new WebSocket(wsurl + '?' + csessid + '&' + cuid + '&' + browser);
// Handle Websocket open event // Handle Websocket open event
websocket.onopen = function (event) { websocket.onopen = function (event) {
@ -304,13 +305,14 @@ An "emitter" object must have a function
var stop_polling = false; var stop_polling = false;
var is_closing = false; var is_closing = false;
var csessid = window.csessid; var csessid = window.csessid;
var cuid = window.cuid;
// initialize connection, send csessid // initialize connection, send csessid
var init = function() { var init = function() {
$.ajax({type: "POST", url: "/webclientdata", $.ajax({type: "POST", url: "/webclientdata",
async: true, cache: false, timeout: 50000, async: true, cache: false, timeout: 50000,
datatype: "json", datatype: "json",
data: {mode: "init", csessid: csessid, browserstr: browser}, data: {mode: "init", csessid: csessid, cuid: cuid, browserstr: browser},
success: function(data) { success: function(data) {
open = true; open = true;
@ -336,7 +338,7 @@ An "emitter" object must have a function
async: true, cache: false, timeout: 30000, async: true, cache: false, timeout: 30000,
dataType: "json", dataType: "json",
data: {mode: inmode == null ? 'input' : inmode, data: {mode: inmode == null ? 'input' : inmode,
data: JSON.stringify(data), 'csessid': csessid}, data: JSON.stringify(data), 'csessid': csessid, 'cuid': cuid},
success: function(req, stat, err) { success: function(req, stat, err) {
stop_polling = false; stop_polling = false;
}, },
@ -356,7 +358,7 @@ An "emitter" object must have a function
$.ajax({type: "POST", url: "/webclientdata", $.ajax({type: "POST", url: "/webclientdata",
async: true, cache: false, timeout: 60000, async: true, cache: false, timeout: 60000,
dataType: "json", dataType: "json",
data: {mode: 'receive', 'csessid': csessid}, data: {mode: 'receive', 'csessid': csessid, 'cuid': cuid},
success: function(data) { success: function(data) {
// log("ajax data received:", data); // log("ajax data received:", data);
if (data[0] === "ajax_keepalive") { if (data[0] === "ajax_keepalive") {
@ -411,7 +413,7 @@ An "emitter" object must have a function
cache: false, cache: false,
timeout: 50000, timeout: 50000,
dataType: "json", dataType: "json",
data: {mode: 'close', 'csessid': csessid}, data: {mode: 'close', 'csessid': csessid, 'cuid': cuid},
success: function(data){ success: function(data){
is_closing = false; is_closing = false;

View file

@ -40,6 +40,15 @@ JQuery available.
}) })
</script> </script>
<!-- Generate a low-quality UID to uniquely identify client tabs -->
<script language="javascript" type="text/javascript">
function generateUID() {
return Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
}
var cuid = generateUID();
</script>
<!-- Set up Websocket url and load the evennia.js library--> <!-- Set up Websocket url and load the evennia.js library-->
<script language="javascript" type="text/javascript"> <script language="javascript" type="text/javascript">
{% if websocket_enabled %} {% if websocket_enabled %}