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:
# client will connect with wsurl?csessid&browserid
# client will connect with wsurl?csessid&page_id&browserid
webarg = self.http_request_uri.split("?", 1)[1]
except IndexError:
# 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))
return None
self.csessid, *browserstr = webarg.split("&", 1)
if browserstr:
self.browserstr = str(browserstr[0])
self.csessid, *cargs = webarg.split("&", 2)
if len(cargs) == 1:
self.browserstr = str(cargs[0])
elif len(cargs) == 2:
self.page_id = str(cargs[0])
self.browserstr = str(cargs[1])
if 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"))
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):
"""
Get browser-string out of the request.
@ -313,10 +325,10 @@ class AjaxWebClient(resource.Resource):
def client_disconnect(self, csessid):
"""
Disconnect session with given csessid.
Disconnect session with given id.
Args:
csessid (int): Session id.
csessid (int): Client page+session id.
"""
if csessid in self.requests:
@ -334,7 +346,8 @@ class AjaxWebClient(resource.Resource):
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)
remote_addr = ip_from_request(request)
@ -349,9 +362,9 @@ class AjaxWebClient(resource.Resource):
sess.client = self
sess.init_session("ajax/comet", remote_addr, self.sessionhandler)
sess.csessid = csessid
sess.csessid = session_id+page_id
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)
if uid:
# the client session is already logged in
@ -359,7 +372,7 @@ class AjaxWebClient(resource.Resource):
sess.logged_in = True
# watch for dead links
self.last_alive[csessid] = (time.time(), False)
self.last_alive[sess.csessid] = (time.time(), False)
if not self.keep_alive:
# the keepalive is not running; start it.
self.keep_alive = LoopingCall(self._keepalive)
@ -373,7 +386,7 @@ class AjaxWebClient(resource.Resource):
# actually do the connection
sess.sessionhandler.connect(sess)
return jsonify({"msg": host_string, "csessid": csessid})
return jsonify({"msg": host_string, "csessid": session_id})
def mode_keepalive(self, request):
"""
@ -384,7 +397,7 @@ class AjaxWebClient(resource.Resource):
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)
return b'""'
@ -397,7 +410,7 @@ class AjaxWebClient(resource.Resource):
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)
cmdarray = json.loads(request.args.get(b"data")[0])
for sess in self.sessionhandler.sessions_from_csessid(csessid):
@ -415,7 +428,7 @@ class AjaxWebClient(resource.Resource):
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)
dataentries = self.databuffer.get(csessid)
@ -441,7 +454,7 @@ class AjaxWebClient(resource.Resource):
request (Request): Incoming request.
"""
csessid = self.get_client_sessid(request)
csessid = self.get_client_sessid(request) + self.get_client_page_id(request)
try:
sess = self.sessionhandler.sessions_from_csessid(csessid)[0]
sess.sessionhandler.disconnect(sess)

View file

@ -220,6 +220,7 @@ An "emitter" object must have a function
var websocket = null;
var wsurl = window.wsurl;
var csessid = window.csessid;
var cuid = window.cuid;
var connect = function() {
if (websocket && websocket.readyState != websocket.CLOSED) {
@ -227,7 +228,7 @@ An "emitter" object must have a function
return;
}
// 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
websocket.onopen = function (event) {
@ -304,13 +305,14 @@ An "emitter" object must have a function
var stop_polling = false;
var is_closing = false;
var csessid = window.csessid;
var cuid = window.cuid;
// initialize connection, send csessid
var init = function() {
$.ajax({type: "POST", url: "/webclientdata",
async: true, cache: false, timeout: 50000,
datatype: "json",
data: {mode: "init", csessid: csessid, browserstr: browser},
data: {mode: "init", csessid: csessid, cuid: cuid, browserstr: browser},
success: function(data) {
open = true;
@ -336,7 +338,7 @@ An "emitter" object must have a function
async: true, cache: false, timeout: 30000,
dataType: "json",
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) {
stop_polling = false;
},
@ -356,7 +358,7 @@ An "emitter" object must have a function
$.ajax({type: "POST", url: "/webclientdata",
async: true, cache: false, timeout: 60000,
dataType: "json",
data: {mode: 'receive', 'csessid': csessid},
data: {mode: 'receive', 'csessid': csessid, 'cuid': cuid},
success: function(data) {
// log("ajax data received:", data);
if (data[0] === "ajax_keepalive") {
@ -411,7 +413,7 @@ An "emitter" object must have a function
cache: false,
timeout: 50000,
dataType: "json",
data: {mode: 'close', 'csessid': csessid},
data: {mode: 'close', 'csessid': csessid, 'cuid': cuid},
success: function(data){
is_closing = false;

View file

@ -40,6 +40,15 @@ JQuery available.
})
</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-->
<script language="javascript" type="text/javascript">
{% if websocket_enabled %}