I am debugging an issue with a Magento system.
The problem is a duplicated Set-Cookie header, like this:
Set-Cookie: flimmit_session=search-0c30086b812519b006aa27ef4f37f15b-24; path=/; domain=.flimmit.com; httponly
Set-Cookie: flimmit_session=search-0c30086b812519b006aa27ef4f37f15b-24; path=/; domain=.flimmit.com; httponly
The cookie is set using php's setcookie command. My question is whether the incorrect use of this function can result in a duplicate Set-Cookie header, or whether I have to look somewhere else for the error...
Yes, calling setcookie() twice with the same data will result in 2 identical Set-Cookie: headers. I have just tried it, and it does.
It shouldn't cause a problem though, the cookie will always have the value defined by the last setcookie() call...
Related
I want to set cookies in laravel blade.php file, not in the controller. How can I set it?
Disclaimer: I will focus my answer on PHP and laravel.
Why not set in controller?
It would really help to know why you cannot / or do not want to set cookies using laravel's cookie Facade in the controller - eg. Cookie::queue, as it's very easy to do!
Here are two ways, from this source.
Via response:
return response(view('welcome'))->cookie('name','value',$min);
Via Queue: Cookie::queue(Cookie::make('name','value',$min)); return view('welcome');
Set-Cookie is a response header, not the body!
Assuming you would set these cookies in PHP , they need to come as part of a response header, and not part of the body (view). This is why you would need to set these in the controller, where you are sending a response!
If you try to use PHP functions to set cookies, you will be met with errors "headers have already been sent"
Per the docs: https://www.php.net/setcookie
setcookie() defines a cookie to be sent along with the rest of the HTTP headers. Like other headers, cookies must be sent before any output from your script (this is a protocol restriction). This requires that you place calls to this function prior to any output, including and tags as well as any whitespace.
To understand what this means, it's helpful to understand the structure of requests and responses:
Requests and Responses are made up of headers and possibly a body.
Note: You can see these in the network tab of your browser's dev tools.
The request headers are like meta data about the request that can tell the server what kind of content is being requested, and who is requesting.
The response headers are like meta data about the response returned that can tell the server what kind of content is being delivered, how long to cache it for, associated cookies that got set.
Example Request Headers:
Content-Type: 'application/json'
Content-Type: 'application/pdf'
Content-Type: 'text/html'
Content-Type: 'text/css'
User-Agent: 'Mozilla/5.0 (<system-information>) <platform> (<platform-details>) <extensions>'
Authorization: 'Bearer <token>'
Example Response Headers:
Content-Type as it may differ from what was requested
Expires: 'Wed, 07 Sep 2022 19:26:49 GMT'
Cross-Origin-Resource-Policy: 'cross-origin'
Date: 'Wed, 07 Sep 2022 19:26:49 GMT'
Content-Length: 0,
Set-Cookie: test_cookie=CheckForPermission; expires=Wed, 07-Sep-2022 19:41:49 GMT; path=/; domain=.doubleclick.net; Secure; HttpOnly; SameSite=none
Notably: - Set-Cookie - tells the browser to add these cookies to application storage (you can view these in application / storage tabs in dev tools)
The response header can have Set-Cookie, not the request header. This makes sense, as usually the cookie information is going to come from the "answer" (response) to the "question" (request) by way of performing some logic, eg - this user is authenticated, here's a cookie to keep their session in place.
Also: Secure & HTTP only Cookies
Cookies can get set with a few options - secure only, and http only. These mean that the cookie must be Set on secure connections (https) and the http only can come from a response and cannot be overridden by JavaScript adjusting (client side)
Example of options for Laravel's Cookie::queue facade:
// $name, $value, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true
Cookie::queue($name, $value, $ttl, $path, $domain, $secure, $httpOnly);
ttl = "time to live" or how long until it expires eg. 2 minutes
My goal is to do programmatically logout from controller. I use this nice solution. Everything works fine except that LONGSESS (renamed REMEMBERME) cookie not deleted. It deleted but not :)
Logout in controller code:
$response = $this->redirectToRoute('homepage');
$response->headers->clearCookie('LONGSESS');
return $response;
So, call this action.
Request headers for this action (as expected):
Cookie SESS=n4jbl1m61l6bceesbeusrbq044; LONGSESS=QXBwQnVuZGxlXEVudGl0eVxVc2VyOmRYTmxja0IxYzJWeUxtTnZiUT09OjE0NDgyMDMyMjQ6ZTFhNzBlNGEyMWM4NGM3N2UzYmI3ZmJiNWIzMGM5MDg2ZDAyOWY1ZGVhMWI4NTYyNGQ0OTJmNjVmNmRjOTY2NQ%3D%3D
Response headers to this action (as expected):
Set-Cookie:SESS=ai1gt79r49o184du3tknv7tdf6; path=/; domain=.myhost.local
Set-Cookie:LONGSESS=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; httponly
Set-Cookie:SESS=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; httponly
Redirect headers (as expected):
Location:/app_dev.php/
Next request headers to homepage (NOT as expected - LONGSESS value is the same as previous request):
Cookie:LONGSESS=QXBwQnVuZGxlXEVudGl0eVxVc2VyOmRYTmxja0IxYzJWeUxtTnZiUT09OjE0NDgyMDMyMjQ6ZTFhNzBlNGEyMWM4NGM3N2UzYmI3ZmJiNWIzMGM5MDg2ZDAyOWY1ZGVhMWI4NTYyNGQ0OTJmNjVmNmRjOTY2NQ%3D%3D; SESS=ai1gt79r49o184du3tknv7tdf6
So user is not logged out.
How may it be? LONGSESS cookie set to deleted, expired but next request has the same value?
The solution is to set third argument domain in clearCookie method call. It have to be equals to domain in session settings:
framework:
session:
cookie_domain: YOUR-DOMAIN.COM
and
firewalls:
your_firewall:
remember_me:
domain: YOUR-DOMAIN.COM
So, the right way:
$response->headers->clearCookie('LONGSESS', '/', 'YOUR-DOMAIN.COM');
Have you tried:
$response->sendHeaders();
right after:
$response->headers->clearCookie('LONGSESS');
?
A centain web client that I need to support, is sending back the Cookies header to my application twice in the HTTP headers, this in turn is making PHP unable to read the correct value for the cookie thus ignoring the session.
Here is the relevant part of the request I am seeing:
GET / HTTP/1.1
Cache-Control: max-age=0
Accept-Language: en-US
Cookie: PHPSESSID=49af82ddf12740e6a35b15985e93d91a
Connection: Keep-Alive
Cookie: PHPSESSID=49af82ddf12740e6a35b15985e93d91a
[...] Other irrelevant headers
I have two questions:
Is that a PHP bug? or is the behavior undefined when the client sends that same header twice?
Is there a quick workaround to make things work without having to manually parse the HTTP headers so I can read the right value of the cookie (and session) in my application? Or should I manually parse the HTTP header to set the session to its correct value?
According to the HTTP spec, a double header simply concatenates the values together with a comma, making it:
Cookie: PHPSESSID=49af82ddf12740e6a35b15985e93d91a, PHPSESSID=49af82ddf12740e6a35b15985e93d91a
PHP should be able to parse the cookies, but the behavior of sessions is undefined when there are two session IDs.
I strongly recommend fixing the client. If that's not an option, you'll have to parse the headers manually.
So I just now learned of the X-Robots-Tag which can be set as part of a server response header. Now that I have learned about this particular field, I am wondering if there are any other specific fields I should be setting when I output a webpage via PHP? I did see this list of responses, but what should I be manually setting? What do you like to set manually?
Restated, in addition to...
header('X-Robots-Tag: noindex, nofollow, noarchive, nosnippet', true);
...what else should I be setting?
Thanks in advance!
You don't necessarily need to set any of them manually, and I don't send any unless absolutely necessary: most response headers are the web server's job, not the application's (give or take Location & situational cache-related headers).
As for the "X-*" headers, the X implies they aren't "official," so browsers may or may not interpret them to mean anything - like, you can add an arbitrary "X-My-App-Version" header to a public project to get a rough idea of where people are using it, but it's just extra info unless the requester knows what to do with it.
I think most X-headers are more commonly delivered via HTML as meta tags already. For example, <meta name="robots" content="noindex, nofollow, (etc)" />, which does the same as X-Robots-Tag. That's arguably better handled with the meta tag version anyway, since it won't trip over output buffering as header() can do, and it will be naturally cached since it's part of the page.
These are headers from Stackoverflow (this page), so the answer is, probably none.
You don't want your site indexed (noindex)?
Status=OK - 200
Cache-Control=public, max-age=60
Content-Type=text/html; charset=utf-8
Content-Encoding=gzip
Expires=Tue, 28 Sep 2010 01:23:00 GMT
Last-Modified=Tue, 28 Sep 2010 01:22:00 GMT
Vary=*
Set-Cookie=usr=t=&s=; domain=.stackoverflow.com; expires=Mon, 28-Mar-2011 01:22:00 GMT; path=/; HttpOnly
Date=Tue, 28 Sep 2010 01:21:59 GMT
Content-Length=6929
This header comes handy to me. Characters are displayed correctly, even if meta tag is missing.
Content-Type: text/html; charset=utf-8
I login to a website and it returns a cookie via the header.
The cookies name is fb_cookie. I try to read it with the below PHP code but it returns nothing. How can I fetch a cookie set via the header?
echo $_COOKIE["fb_cookie"];
The response is this from the header (read by the Poster plugin in Firefox).
fb_cookie=1554e662b9914b5d640d655f-627185705%7C6LneHfe-wWAworIG2hTHSzxuqkw.; path=/; expires=Thu, 07-Jul-2011 12:57:05 GMT _lambda_session=BAh7BzoMdXNlcl9pZGkBkToPc2Vzc2lvbl9pZCIlOGY2Y2U2ZDhlMDcyNTdjMDM4ZjYyNjQ4ZmU5OGU1ZTU%3D--3e60eb15a406a9320f7ab83fb7e0866198f4b6c7; path=/; HttpOnly
Please help!
$_COOKIE contains the cookies the user sends to your PHP page. You want the cookie which another page sends to you.
If you use curl to retrieve the page, the CURLOPT_COOKIEJAR option may help.