cookies-based sessions

Related: https://pagure.io/koji/issue/3393
This commit is contained in:
Tomas Kopecek 2022-06-27 12:29:25 +02:00
parent 08a9fb8879
commit 850a161e2b
3 changed files with 48 additions and 21 deletions

View file

@ -19,6 +19,7 @@
# Mike McLean <mikem@redhat.com>
import datetime
import http.cookies
import inspect
import logging
import os
@ -811,6 +812,19 @@ def application(environ, start_response):
('Content-Length', str(len(response))),
('Content-Type', "text/xml"),
]
cookies = http.cookies.SimpleCookie(environ.get('HTTP_SET_COOKIE'))
if hasattr(context, 'session') and context.session.logged_in:
cookies['session-id'] = context.session.id
cookies['session-key'] = context.session.key
cookies['callnum'] = context.session.callnum
cookies['logged_in'] = "1"
else:
# good for not mistaking for the older hub with small overhead
cookies['logged_in'] = "0"
for c in cookies.values():
c.path = '/'
c.secure = True
headers.append(('Set-Cookie', c.OutputString()))
start_response('200 OK', headers)
if h.traceback:
# rollback

View file

@ -57,6 +57,7 @@ except ImportError: # pragma: no cover
from fnmatch import fnmatch
import dateutil.parser
import http.cookies
import requests
import six
import six.moves.configparser
@ -2701,10 +2702,11 @@ class ClientSession(object):
return self._prepUpload(*args, **kwargs)
args = encode_args(*args, **kwargs)
if self.logged_in:
sinfo = self.sinfo.copy()
sinfo['callnum'] = self.callnum
for c in self.rsession.cookies:
if c.name == 'callnum':
c.value = str(self.callnum)
self.callnum += 1
handler = "%s?%s" % (self.baseurl, six.moves.urllib.parse.urlencode(sinfo))
handler = self.baseurl
elif name == 'sslLogin':
handler = self.baseurl + '/ssllogin'
else:
@ -2799,6 +2801,13 @@ class ClientSession(object):
warnings.simplefilter("ignore")
r = self.rsession.post(handler, **callopts)
r.raise_for_status()
if self.logged_in and len(r.cookies.items()) == 0:
# we have session, sent the cookies, but server is old
# and didn't sent them back, use old url-encoded style
sinfo = self.sinfo.copy()
handler = "%s?%s" % (handler, six.moves.urllib.parse.urlencode(sinfo))
r = self.rsession.post(handler, **callopts)
r.raise_for_status()
try:
ret = self._read_xmlrpc_response(r)
finally:

View file

@ -29,7 +29,6 @@ import string
import six
from six.moves import range, urllib
import koji
from .context import context
from .util import to_list
@ -79,24 +78,23 @@ class Session(object):
self._perms = None
self._groups = None
self._host_id = ''
# get session data from request
if args is None:
environ = getattr(context, 'environ', {})
args = environ.get('QUERY_STRING', '')
if not args:
self.message = 'no session args'
return
args = urllib.parse.parse_qs(args, strict_parsing=True)
environ = getattr(context, 'environ', {})
# prefer new cookie-based sessions
if 'HTTP_COOKIE' in environ:
cookies = http.cookies.SimpleCookie(environ['HTTP_COOKIE'])
try:
id = int(cookies['session-id'].value)
key = str(cookies['session-key'].value)
except KeyError as field:
raise koji.AuthError('%s not specified in session args' % field)
try:
callnum = int(cookies['callnum'].value)
except KeyError:
callnum = None
else:
self.message = 'no session cookies'
return
hostip = self.get_remote_ip(override=hostip)
try:
id = int(args['session-id'][0])
key = args['session-key'][0]
except KeyError as field:
raise koji.AuthError('%s not specified in session args' % field)
try:
callnum = args['callnum'][0]
except Exception:
callnum = None
# lookup the session
# sort for stability (unittests)
@ -500,6 +498,12 @@ class Session(object):
insert.execute()
context.cnx.commit()
# update it here, so it can be propagated to the cookies in kojixmlrpc.py
context.session.id = session_id
context.session.key = key
context.session.logged_in = True
context.session.callnum = 0
# return session info
return {'session-id': session_id, 'session-key': key}