def getRequestId(self, request): """Return the browser id encoded in request as a string Return None if an id is not set. For example: >>> from zope.publisher.http import HTTPRequest >>> request = HTTPRequest(StringIO(''), {}, None) >>> bim = CookieClientIdManager() Because no cookie has been set, we get no id: >>> bim.getRequestId(request) is None True We can set an id: >>> id1 = bim.generateUniqueId() >>> bim.setRequestId(request, id1) And get it back: >>> bim.getRequestId(request) == id1 True When we set the request id, we also set a response cookie. We can simulate getting this cookie back in a subsequent request: >>> request2 = HTTPRequest(StringIO(''), {}, None) >>> request2._cookies = dict( ... [(name, cookie['value']) ... for (name, cookie) in request.response._cookies.items() ... ]) And we get the same id back from the new request: >>> bim.getRequestId(request) == bim.getRequestId(request2) True """ request = IHTTPApplicationRequest(request) # If there is an id set on the response, use that but don't trust it. # We need to check the response in case there has already been a new # session created during the course of this request. response_cookie = request.response.getCookie(self.namespace) if response_cookie: sid = response_cookie['value'] else: sid = request.getCookies().get(self.namespace, None) if sid is None or len(sid) != 54: return None s, mac = sid[:27], sid[27:] if (digestEncode(hmac.new(s, self.secret, digestmod=sha).digest()) != mac): return None else: return sid
def getRequestId(self, request): """Return the browser id encoded in request as a string Return `None` if an id is not set. For example: >>> from io import BytesIO >>> from zope.publisher.http import HTTPRequest >>> request = HTTPRequest(BytesIO(), {}, None) >>> bim = CookieClientIdManager() Because no cookie has been set, we get no id: >>> bim.getRequestId(request) is None True We can set an id: >>> id1 = bim.generateUniqueId() >>> bim.setRequestId(request, id1) And get it back: >>> bim.getRequestId(request) == id1 True When we set the request id, we also set a response cookie. We can simulate getting this cookie back in a subsequent request: >>> request2 = HTTPRequest(BytesIO(), {}, None) >>> request2._cookies = dict( ... [(name, cookie['value']) ... for (name, cookie) in request.response._cookies.items() ... ]) And we get the same id back from the new request: >>> bim.getRequestId(request) == bim.getRequestId(request2) True We allow unicode values as input, even though we work in the byte-based realm of HMAC: >>> id_uni = bim.generateUniqueId() >>> bim.setRequestId(request, id_uni) >>> bim.getRequestId(request) == id_uni True If the cookie data has been tampered with (doesn't correspond to our secret), we will refuse to return an id: >>> cookie = request.response.getCookie(bim.namespace) >>> cookie['value'] = 'x' * len(cookie['value']) >>> bim.getRequestId(request) is None True If another server is managing the ClientId cookies (Apache, Nginx) we're returning their value without checking: >>> bim.namespace = 'uid' >>> bim.thirdparty = True >>> request3 = HTTPRequest(BytesIO(), {}, None) >>> request3._cookies = {'uid': 'AQAAf0Y4gjgAAAQ3AwMEAg=='} >>> bim.getRequestId(request3) 'AQAAf0Y4gjgAAAQ3AwMEAg==' """ response_cookie = request.response.getCookie(self.namespace) if response_cookie: sid = response_cookie['value'] else: request = IHTTPApplicationRequest(request) sid = request.getCookies().get(self.namespace, None) if self.thirdparty: return sid # If there is an id set on the response, use that but # don't trust it. We need to check the response in case # there has already been a new session created during the # course of this request. if sid is None or len(sid) != 54: return None s, mac = sid[:27], sid[27:] # HMAC is specified to work on byte strings only so make # sure to feed it that by encoding mac_with_my_secret = hmac.new(self.secret.encode(), s.encode(), digestmod=sha1).digest() mac_with_my_secret = digestEncode(mac_with_my_secret).decode() if mac_with_my_secret != mac: return None return sid
def getRequestId(self, request): """Return the browser id encoded in request as a string Return None if an id is not set. For example: >>> from zope.publisher.http import HTTPRequest >>> request = HTTPRequest(StringIO(''), {}, None) >>> bim = CookieClientIdManager() Because no cookie has been set, we get no id: >>> bim.getRequestId(request) is None True We can set an id: >>> id1 = bim.generateUniqueId() >>> bim.setRequestId(request, id1) And get it back: >>> bim.getRequestId(request) == id1 True When we set the request id, we also set a response cookie. We can simulate getting this cookie back in a subsequent request: >>> request2 = HTTPRequest(StringIO(''), {}, None) >>> request2._cookies = dict( ... [(name, cookie['value']) ... for (name, cookie) in request.response._cookies.items() ... ]) And we get the same id back from the new request: >>> bim.getRequestId(request) == bim.getRequestId(request2) True Test a corner case where Python 2.6 hmac module does not allow unicode as input: >>> id_uni = unicode(bim.generateUniqueId()) >>> bim.setRequestId(request, id_uni) >>> bim.getRequestId(request) == id_uni True If another server is managing the ClientId cookies (Apache, Nginx) we're returning their value without checking: >>> bim.namespace = 'uid' >>> bim.thirdparty = True >>> request3 = HTTPRequest(StringIO(''), {}, None) >>> request3._cookies = {'uid': 'AQAAf0Y4gjgAAAQ3AwMEAg=='} >>> bim.getRequestId(request3) 'AQAAf0Y4gjgAAAQ3AwMEAg==' """ response_cookie = request.response.getCookie(self.namespace) if response_cookie: sid = response_cookie['value'] else: request = IHTTPApplicationRequest(request) sid = request.getCookies().get(self.namespace, None) if self.thirdparty: return sid else: # If there is an id set on the response, use that but # don't trust it. We need to check the response in case # there has already been a new session created during the # course of this request. if sid is None or len(sid) != 54: return None s, mac = sid[:27], sid[27:] # call encode() on value s a workaround a bug where the hmac # module only accepts str() types in Python 2.6 if (digestEncode(hmac.new( self.secret, s.encode(), digestmod=sha1 ).digest()) != mac): return None else: return sid