I'm using Firefox 3.6.8 for these tests.
I'm setting a cookie within the response headers of my web app using:
Set-Cookie: session=7878dfdsfjsdf89sd89f8df9
This does not seem to override the session Cookie.
When a request is performed instead Firefox even sends duplicate cookies:
Cookie: session=7d75cd8f55895cbccb0d31ee07c7afc0;
session=671e8448a5cebda0442005a186cf69a3;
4cb6f2d75c9ffc8916cb55bcbaafecd8
What is going on??
Any ideas would be great!! =)
This is quite disastrous in my case... if someone could explain what's going on it would really help me out!
If you don't specify the path or domain for a cookie when setting it, it defaults to the current path and current hostname. If you then go ahead and try setting the same cookie name from a URL with a different path or hostname, it will add a new cookie instead of replacing the old one.
I suspect what you want to do is just set a cookie with a global path for your site and for your entire domain. So something like this:
Set-Cookie: session=7878dfdsfjsdf89sd89f8df9; path=/; domain=.mysite.com
You can delete the previous cookie using the response object.
response.delete_cookie(cookie_key)
The set of cookies is available via the request object in the request.COOKIES dictionary, and you can obtain the key from there.
Since you're using Django, here's how you might do this in the view function:
def my_view(request):
# do some work and create a response object
response = HttpResponse(some_content)
# first delete any previously set cookie named "session"
if 'session' in request.COOKIES:
response.delete_cookie('session')
# set the new cookie
response.set_cookie('session', <cookie value goes here>')
return response
Related
I want my application to be able to detect the user's language to serve the corresponding page to them. My idea was to use #before.request to read the Accepted-Languages header, match it against the app's supported languages, and set a cookie if needed, but it seems that the last step is not achievable.
Here is the code for that:
#app.before_request
def before_request_callback():
if request.cookies.get('lang'):
pass
else:
lang = request.accept_languages.best_match(supported_languages)
print(lang)
#I would like to set the cookie here
I thought about setting the cookie in the response object directly in the decorator (resp.set_cookie()) and thus reformatted all the returns in my app to look like this
#app.route("/")
def hello():
resp = make_response(render_template('index.html'))
return resp
to maybe be able to fetch the cookie and attach it to this response, but since the response is created afterwards in the endpoitn function, i have no idea how to do that either.
I also thought about creating the response directly in the decorator, but since i need the return condition, i don't know if thats possible
I think you're trying to use a cookie when you don't need to. As you noted, you can only set cookies on the response. You send the browser cookies in the response and then it re-sends them to you in any subsequent request. But it's already sending you the Accept-Language. So there's no point in setting a cookie on the request. It's already arrived, and already contains what you need.
Instead of getting hung up on setting cookies, just consult the request at the point that you're generating the response to ensure that the served content is in the appropriate language.
from flask import request
#app.route("/")
def hello():
lang = request.accept_languages.best_match(supported_languages)
return render_template(f'{lang}/index.html')
In this way, I want to set my cookie. But it fails to set.
#app.route('/')
def index():
res = flask.make_response()
res.set_cookie("name", value="I am cookie")
When I print res it shows <Response 0 bytes [200 OK] But not set cookie
You have to return the response after setting the cookie.
#app.route('/')
def index():
resp = make_response(render_template(...))
resp.set_cookie('somecookiename', 'I am cookie')
return resp
This way a cookie will be generated in your browser, but you can get this cookie in the next request.
#app.route('/get-cookie/')
def get_cookie():
username = request.cookies.get('somecookiename')
The cookie you set will be visible if you either use other tools to see it (ex: Press F12 for Developer Tools in Firefox or Chrome) or use a piece of code of JavaScript inside the rendered response.
The cookies are set on the browser by either browser itself (JavaScript) or as a response from a server.
The difference is of great importance as even if the cookie is set by the server the cookie might not be set on the browser (ex: cases where cookie are completely disabled or discarded).
So even if the server might tell "I set up the cookie" - the cookie might not be present on the browser.
For the server to be sure that the cookie was set a subsequent request from the browser is needed (with the cookie present in the request's headers).
So even if the Flask's response (res variable) will mention that the cookie is set we can only be sure that it was set by the server but it will have no confirmation about it from the browser.
Advanced
Another aspect is about how Flask or any other API is creating the responses. As the payload (html/template code) and headers (cookie) are set at same time - the "code" inside the payload (html/template code) might not have access to the cookie.
So you might not be able to set a cookie and display it in the response.
An idea might be to (be able to) first set the cookies and THEN to render the context and the order of setup to be important - so that the html/template to be aware of already setup values. But even in this case is only the server's confirmation that it set up the cookie.
A solution
#app.route('/')
def index():
res = flask.make_response()
res.set_cookie("name", value="I am cookie")
# redirect to a page that display the cookie
resp.headers['location'] = url_for('showcookies')
return resp, 302
This response will set cookie in you browser
def func():
response = make_response( render_template() )
response.set_cookie( "name", "value" )
return response
I am trying to write a small script that will allow me to see information related to the cookies set by my website.
I want to know if it has secure or httpOnly flags set on them. But so far I wasn't able to do it, I only figured out how to get cookie names and values. Here is my current code:
r = requests.post('url', data=data, headers=headers)
for (name, cookie) in r.cookies.items():
print name, cookie
So far this works fine, but I want to get information related to the cookies, not the value itself. Cookie meta-data if you will.
How can I achieve that?
You can extract the information from each cookie individually:
import requests
r = requests.post('http://www.about.com')
for cookie in r.cookies:
print(cookie.__dict__)
print(cookie.secure)
This is because r.cookies is an instance of RequestsCookieJar which extends from CookieJar (Python 2: cookielib.CookieJar, Python 3: http.cookiejar.CookieJar). A CookieJar has Cookie objects.
References:
cookielib: https://docs.python.org/2.7/library/cookielib.html
cookielib.Cookie.secure: https://docs.python.org/2.7/library/cookielib.html#cookielib.Cookie.secure
https://stackoverflow.com/a/27523891/295246
Update:
I have not found a way to retrieve the httponly value from a Cookie object. In Python 3, you can define a Morsel object via a dictionary, and it considers httponly to be a standard attribute of a cookie (https://docs.python.org/3/library/http.cookies.html), but I couldn't find any reference to httponly in the defining specification RFC2109 (https://www.ietf.org/rfc/rfc2109.txt).
That said, if httponly is in fact a non-standard attribute, then you can use the following to check if a cookie has it:
cookie.has_nonstandard_attr('httponly')
Under Python 3, I was not able to retrieve the httpOnly flag from the following:
cookie.get_nonstandard_attr('httpOnly')
and
cookie.has_nonstandard_attr('httpOnly')
returned False even if the httpOnly flag was included with the cookie.
This didn't work with any of the variations of httponly, HttpOnly, etc. either.
Using #HEADLESS_0NE's post, I found you can retrieve the flag by looking at the _rest field in cookie.__dict__. If httpOnly is included in the cookie,
cookie.__dict__['_rest']
will return something like this:
{'HttpOnly': None, ...}
Thus, here is a small helper function to check if a cookie has the httpOnly flag.
def has_http_only(cookie):
extra_args = cookie.__dict__.get('_rest')
if extra_args:
for key in extra_args.keys():
if key.lower() == 'httponly':
return True
return False
The secure flag is automatically added to the cookie object and can be retrieved using cookie.secure.
I am writing a Proxy Server where I will intercept a request, and check the header to see if it has a cookie named URID, and if it does not, I want to redirect the request to a fw.asta.com, see if this domain has a cookie called URID, and if it doesn't, I want to set the cookie for fw.cisco.com, and then redirect to the originally intended site, and then set the same cookie for that site as well. If the cookie exists for the fw.asta.com site, I will use that cookie to redirect to the originally intended site, and if the originally intended site has the URID cookie, I will simply serve the request on behalf of the site.
So I have been struggling with this for quite some time. I have a feeling like I don't understand what actually happens when I set a cookie during a redirection.
I have this code right here:
def do_GET(self):
#seperate the path into parts
(scm, netloc, path, params, query, fragment) = urlparse.urlparse(self.path, 'http')
#check the header for the urid cookie, returns the URID if present
urid = self.find_urid()
if netloc == 'fw.asta.com':
if urid:
#redirect to the originally intended site and set the cookie
path = self.path[23:]
self.redirect_with_urid(path, urid)
else:
#redirect to fw.asta.com
urid = 333
self.redirect_with_urid(self.path, urid)
else:
if urid:
#simply serve the site because if has the URID
self.final_destination()
else:
#no urid, so we need to go the fw.asta.com to check if the urid is there
self.redirect('http://fw.asta.com/?url=' + str(self.path))
As you can see the logic makes sense, however when I run the code, I run into an infinite redirect loop to the originally intended site.
When I get the redirect response, I can clearly see that the set-cookie field is there, however, when I get the redirected request, it does not send the cookie back to me.
Is this even the right way to go about the problem? Any advice would be appreciated.
I am trying to setup token based authentication in python. using Django/DRF. but this is more about http in general i think.
When users put in username/password I return to them their token via JSON.
The client then can post the token in HTTP Header for me to check.
My problem is I want the token to persist in the header automatically, just like cookies.
When the server says "set-cookie" to browser (Chrome/FF), the browser will automatically send up the cookie without me actually doing anything. Is there something I can do with this token?
I have tried storing it in header: "Authorization", but the browser didn't return it. Is there something like "Set-Authorization"?
thanks
No, only cookies stored in browser persistently. All other headers are transient by HTTP protocol definition.