I am familiar with assigning, creating cookies in Python. But I am unsure how to create a cookie that will last until the current browser session is closed(so I have a very rudimentary way of telling when the user is returning to my website).
So which cookie header do I set to make sure the cookie will expire/delete when the browser is closed in Python? Do I use the SimpleCookie object or another object for this?
This thread says I set the cookie_lifetime flag/header in PHP, but what about for python? http://bytes.com/topic/php/answers/595383-how-declare-cookie-will-destroy-after-browser-closed
Would this create a cookie that expires on closing of the browser?
cookie = Cookie.SimpleCookie()
cookie["test"] = "MYTEST"
cookie["test"]['expires'] = 0 # or shd I set the max-age header instead?
print str(cookie) + "; httponly"
Just leave out the "expires" value altogether, i.e. don't set it to anything. See the Wikipedia entry for details:
Set-Cookie: made_write_conn=1295214458; path=/; domain=.foo.com
[...]
The second cookie made_write_conn does not have expiration date, making it a session cookie. It will be deleted after the user closes his/her browser
In Python:
In [11]: from Cookie import SimpleCookie
In [12]: c = SimpleCookie()
In [13]: c['test'] = 'MYTEST'
In [14]: print c
Set-Cookie: test=MYTEST
Mack,
Your answer looks correct to me. Setting "expires" = 0 on the Morsel object should do what you want. Have you tested it?
Looks like max-age is not supported by IE:
http://mrcoles.com/blog/cookies-max-age-vs-expires/
Related
My use case is to generate token for reset password api. Which I am doing with itsdangerous library in python.
https://pythonhosted.org/itsdangerous/.
This token(within reset password link) is forwarder through email to client, the token has expiry time limit which is validated and after that password reset can go through successfully.
Issue here is that once password reset is successful how do I make sure the same token(email link) cannot be used again within the expiry time limit. I can see itsdangerous has URLSafeTimedSerializer which helps evaluate during the validation phase on how old the token is. On the other hand TimedJSONWebSignatureSerializer helps set the expiry time while generating token. Please check the attached piece of code.
Is there a better way to expire token forcefully? If not what would be the best way to save the state of token that it has been used?
import itsdangerous
key = "test"
# signer = itsdangerous.URLSafeTimedSerializer(key)
signer = itsdangerous.TimedJSONWebSignatureSerializer(key, expires_in=5)
email = "email#test.com"
# token = email # to be used with URLSafeTimedSerializer
token = signer.dumps({"email": email})
print token
# print signer.loads(token, max_age=5) # to be used with URLSafeTimedSerializer
print str(signer.loads(token)["email"]) # to be used with TimedJSONWebSignatureSerializer
Once your token is generated and signed it remains valid until it expires. You cannot change that anymore. With that in mind, it also means that you cannot change any of its payload once it was signed, otherwise it will be rendered invalid (due to an invalid signature).
One thing you could do however is to generate an unique key ("some_key") once you generate your token and store the key in your database. In the end, the tokens payload which will be issued to the user could look like this: {"email": email, "reset_key": "some_key"}.
Each time someone would try to reset his password, you would simply verify that key first in order to allow or reject a request.
Once the reset was successfull you would simply remove that key from your database (or flag it as invalid). That would make the following requests containing the same token invalid, even though the token itself is still valid from an expiry perspective.
I hope that helps!
I realise this is a late answer, so added for the benefit of others finding this question.
Another approach might be to use a boolean session variable such as tokenused and set this to True once the token has been de-serialised; thus invalidating the use of the token.
For example, using the session object in Flask:
uid = {}
try:
if not session['tokenused']:
session['tokenused'] = True
s = Serializer(app.config['SECRET_KEY'])
uid = s.loads(token)
except Exception as err:
errors.internal_server_error(err)
return uid
I am using python and cookielib to talk to an HTTP server that has its date incorrectly set. I have no control over this server, so fixing its time is not a possibility. Unfortunately, the server's incorrect time messes up cookielib because the cookies appear to be expired.
Interestingly, if I go to the same website with any web browser, the browser accepts the cookie and it gets saved. I assume that modern webbrowsers come across misconfigured web servers all the time and see that their Date header is set incorrectly, and adjust cookie expiration dates accordingly.
Has anyone come across this problem before? Is there any way of handling it within Python?
I hacked together a solution that includes live-monkey patching of the urllib library. Definitely not ideal, but if others find a better way, please let me know:
cook_proc = urllib2.HTTPCookieProcessor(cookielib.LWPCookieJar())
cookie_processing_lock = threading.Lock()
def _process_cookies(request, response):
'''Process cookies, but do so in a way that can handle servers with bad
clocks set.'''
# We do some real monkey hacking here, so put it in a lock.
with cookie_processing_lock:
# Get the server date.
date_header = cookielib.http2time(
response.info().getheader('Date') or '')
# Save the old cookie parsing function.
orig_parse = cookielib.parse_ns_headers
# If the server date is off by more than an hour, we'll adjust it.
if date_header:
off_by = time.time() - date_header
if abs(off_by) > 3600:
logging.warning("Server off %.1f hrs."%(abs(off_by)/3600))
# Create our monkey patched
def hacked_parse(ns_headers):
try:
results = orig_parse(ns_headers)
for r in results:
for r_i, (key, val) in enumerate(r):
if key == 'expires':
r[r_i] = key, val + off_by
logging.info("Fixing bad cookie "
"expiration time for: %s"%r[0][0])
logging.info("COOKIE RESULTS: %s", results)
return results
except Exception as e:
logging.error("Problem parse cookie: %s"%e)
raise
cookielib.parse_ns_headers = hacked_parse
response = cook_proc.http_response(request, response)
# Make sure we set the cookie processor back.
cookielib.parse_ns_headers = orig_parse
for some reason I'm unable to retrieve a secure cookie I've set with tornado. Using firebug I can see the cookie and it's expiration date, but when I try to print or retrieve it, it keeps coming up as None. Is there some way I'm invalidating it that I can't see. This is the code I'm using:
class loginHandler(tornado.web.RequestHandler):
def post(self):
# first type of request made to this page is a post
userEmail = self.get_argument("username")
password = self.get_argument("password")
deviceType = self.get_argument("deviceType")
# get some info from the client header
userIp = self.request.headers['X-Real-Ip']
userAgentInfo = self.request.headers['User-Agent']
result = pumpkinsdb.loginUser(userEmail, password, deviceType, userIp, userAgentInfo)
if result == None:
self.redirect("/")
else:
fullname = pumpkinsdb.pumpkinsdb_user['fullName']
this_page_title = fullname if fullname else pumpkinsdb.pumpkinsdb_user['userEmail']
# successful login set up user's cookies
# self.set_secure_cookie("memberId", str(user['memberId']), expires_days=0.1, secure=True, httponly=True)
self.set_secure_cookie("memberId", str(pumpkinsdb.pumpkinsdb_user['memberId']))
self.write(str(self.get_secure_cookie("memberId")))
time_now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print "{} [{}::get] pid[{}] login requested for user: [{}] from [{}] using [{}]".format(
time_now, self.__class__.__name__, os.getpid(), pumpkinsdb.pumpkinsdb_user['emailAddress'],
pumpkinsdb.pumpkinsdb_user['userIp'], pumpkinsdb.pumpkinsdb_user['userAgentInfo'])
self.render('calendar.html', title = this_page_title)
def get(self):
validSession = self.get_secure_cookie("memberId")
if validSession:
this_page_title = pumpkinsdb.pumpkinsdb_user['fullName']
self.render('calendar.html', title = this_page_title)
else:
print self.get_secure_cookie("memberId")
self.write(str(validSession))
Is your cookie secret changing somehow when you restart the server? If the cookie secret changes, all existing cookies are invalidated. Note that even though the cookie secret should be randomly generated, this doesn't mean you should have something like cookie_secret=os.urandom(16) in your code, because that will generate a new secret every time. Instead, you need to call os.urandom once and save its output somewhere (keep it safe and private, like your TLS keys).
so basically the problem was I had four tornado processes running behind nginx and for each tornado process I generated a unique random string with:
cookie_secret = base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes)
obviously that was my problem because each tornado process had a different secret so when i tried to read it tornado thought it was invalid.
The key is to generate a unique random string but then store it somewhere secure such as in your options:
define(cookie_secret, "934893012jer9834jkkx;#$592920231####")
or whatever string you deem fit.
Thank you to everyone that responded. sorry about that.
I have a site im working on, i want to store a value in a cookie
this is an number, when the user comes to the website, i want to know what the number was on their last visit, so I'm thinking of having a persistant cookie that stores the current value, when the user comes to the site, if there is no session cookie, then the session cookie grabs a copy of the persistant cookie.
This way the session cookie always has the value from the last visit.
how ever it seems that my persistant cookie isnt being persisted even though i've set the expiry date 1 year from now
here is my python code:
persistentCookieKey = category + '_highest_id'
sessionCookieKey = 'session_' + persistentCookieKey + '_highest_id'
persistentCookieValue = request.get_cookie(persistentCookieKey)
if persistentCookieValue == None:
persistentCookieValue = 0 # each time i restart my browser it comes through here!
sessionCookieValue = request.get_cookie(sessionCookieKey)
print 'persistentCookieValue:', persistentCookieValue
print 'sessionCookieValue:', sessionCookieValue
if sessionCookieValue == None:
print 'session cookie not set, setting to:', persistentCookieValue
sessionCookieValue = persistentCookieValue
response.set_cookie(sessionCookieKey, str(persistentCookieValue))
print 'setting persistent cookie to value:', highestId
expireDate = date.today() + timedelta(days=365)
response.set_cookie(persistentCookieKey, str(highestId), expires=expireDate)
highestIdLastVisit = int(sessionCookieValue)
Bottle uses http://docs.python.org/library/cookie.html to implement cookie support. This implementation requires the expires parameter to be a string in the Wdy, DD-Mon-YY HH:MM:SS GMT format. Passing datetime or date objects fails silently.
I'll fix that in future versions of Bottle (hi, I'm the author) but for now I suggest using max_age instead.
Edit: Oh, and I just noticed it is also documented incorrectly. Sorry for that.
Edit2: Fixed (in master)
I'm using ActivePython 2.5.1 and the cookielib package to retrieve web pages.
I'd like to display a given cookie from the cookiejar instead of the whole thing:
#OK to display all the cookies
for index, cookie in enumerate(cj):
print index, ' : ', cookie
#How to display just PHPSESSID?
#AttributeError: CookieJar instance has no attribute '__getitem__'
print "PHPSESSID: %s" % cj['PHPSESSID']
I'm sure it's very simple but googling for this didn't return samples.
Thank you.
The cookiejar does not have a dict-like interface, only iteration is supported. So you have to implement a lookup method yourself.
I am not sure what cookie attribute you want do do the lookup on. Example, using name:
def get_cookie_by_name(cj, name):
return [cookie for cookie in cj if cookie.name == name][0]
cookie = get_cookie_by_name(cj, "PHPSESSID")
If you're not familiar with the [...] syntax, it is a list comprehension. The [0] then picks the first element of the list of matching cookies.