Passing Cookies to a HTTP GET inside of a django middleware for single sign on
I need to implement a single sign for a django app that needs to interact with a 3rd parties single sign on system. The person starts off logged into the other system and they get redirected over to the django app. The django app needs to check every few minutes if that person's session is still active. This is done by making a HTTP GET call and passing in all of the cookies to the HTTP GET request, and it returns back a True or False in the HTTP headers.
I'm going to build this with a django middleware that keeps track of the last time the person had their auth checked and if it is past the limit, I'll ping the server and make sure there session is still valid. If it is, I continue on, if not I redirect them back to the other site to login.
Both sites are under the same domain so we both have access to all of the cookies for the domain.
Now that you have the background, my question is this.
What is the best way to call the HTTP GET with all of the cookies passed in the headers?
In the middleware I have access to all of the cookies from request.COOKIES
I have tried some basic attempts using urllib and httplib2 but they don't seem to be working. Before I spend too much time, I figured I would ask to see if there is a better way to get this done.
Here is my attempt at httplib2
def httplib2_auth(auth_url, cookies):
""" Cookies is a dict of cookies from request.COOKIES in middleware """
http = httplib2.Http()
cookie_str = "; ".join("%s=%s" % (x, cookies[x]) for x in cookies if cookies[x])
headers = {'Cookie': cookie_str}
response, content = http.request(auth_url, 'GET', headers=headers)
if 'AUTHENTICATION-X' in response:
is_valid = response['AUTHENTICATION-X']
if is_valid == 'TRUE':
return True
return False
It doesn't seem to work correctly I always get False as logged in, if I do the get via the browser I get a True. So Maybe I'm settings the cookies wrong?
Here is my attempt at urllib
def urllib_auth(auth_url, cookies)
""" Cookies is a dict of cookies from request.COOKIES in middleware """
cookie_str = "; ".join("%s=%s" % (x, cookies[x]) for x in cookies if cookies[x])
opener = urllib.FancyURLopener()
opener.addheader("Cookie", cookie_s开发者_Python百科tr)
obj = opener.open(auth_url)
result2 = obj.read()
log.info("result = %s " % result2)
obj.close()
I'm not sure how to check the headers using urllib but the body always says false, which means it isn't valid anyway. Once again, not sure if I'm setting the cookies correctly.
I'm going to try to use urllib2 next, I have been avoiding it, since it looks a little over engineered for my taste, I'll post my results when I get them.
I don't have access to the other system that has the single sign on, so I can't see the logs or any of that fun stuff.
EDIT: Added python-requests example and urllib2 example
python-request version, it doesn't set the cookies in the header on the request.
def requests_auth(auth_url, cookies):
cj = cookielib.CookieJar()
for x in cookies:
if len(cookies[x]) > 0:
ck = cookielib.Cookie(version=1, name=x, value=cookies[x],
port=None, port_specified=False, domain='.example.com',
domain_specified=True,
domain_initial_dot=True, path='/',
path_specified=True, secure=False,
expires=None, discard=True,
comment=None, comment_url=None,
rest=None, rfc2109=True)
#log.info(ck)
cj.set_cookie(ck)
log.info("cookies = %s " % cj)
response = requests.get(auth_url, cookies=cj)
log.info("response %s \n" % response)
log.info("response.headers %s \n" % response.headers)
log.info("response.content %s \n" % response.content)
urllib2 version, doesn't look like it is passing the cookies in the header with the request either, I must be doing something wrong with the cookiejar
def urllib2_auth(auth_url, cookies):
log.info("[auth]")
cj = cookielib.CookieJar()
for x in cookies:
if len(cookies[x]) > 0:
ck = cookielib.Cookie(version=1, name=x, value=cookies[x],
port=None, port_specified=False, domain='.example.com',
domain_specified=True,
domain_initial_dot=True, path='/',
path_specified=True, secure=False,
expires=None, discard=True,
comment=None, comment_url=None,
rest=None, rfc2109=True)
log.info(ck)
cj.set_cookie(ck)
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
urllib2.install_opener(opener)
req = Request(auth_url) # create a request object
handle = urlopen(req)
log.info("read = %s " % handle.read())
log.info("info = %s " % handle.info())
Spoofing cookies isn't SSO, it's just spoofing cookies.
The way this "should" work is that either the domain cookie's expiry is literally the same as the session expiry or there's some kind of hash that other apps can use to poll the SSO app for the user's state.
If you're stuck and the SSO vendor is telling you to do it this way, I would seriously question the wisdom of using that vendor, or at the very least push back and tell them to provide a solution that doesn't involve an app impersonating a user.
If the third party isn't "really" SSO and you just have a client/boss telling you "I want the login from site A to work on site B" then, um, upsell to fix it for them ;-)
精彩评论