setcookie() - php 网络函数
setcookie()
(PHP 4, PHP 5, PHP 7)
发送 Cookie
说明
setcookie(string $name[,string $value=""[,int $expire= 0[,string $path=""[,string $domain=""[,bool $secure= false[,bool $httponly= false[,string $samesite=""]]]]]]): boolsetcookie()定义了 Cookie,会和剩下的 HTTP 头一起发送给客户端。和其他 HTTP 头一样,必须在脚本产生任意输出之前发送 Cookie(由于协议的限制)。请在产生任何输出之前(包括和或者空格)调用本函数。
一旦设置 Cookie 后,下次打开页面时可以使用$_COOKIE读取。 Cookie 值同样也存在于$_REQUEST。
参数
RFC 6265提供了setcookie()每个参数的参考标准。
$nameCookie 名称。
$valueCookie 值。这个值储存于用户的电脑里,请勿储存敏感信息。比如$name是'cookiename',可通过$_COOKIE['cookiename']获取它的值。
$expireCookie 的过期时间。这是个 Unix 时间戳,即 Unix 纪元以来(格林威治时间 1970 年 1 月 1 日 00:00:00)的秒数。也就是说,基本可以用time()函数的结果加上希望过期的秒数。或者也可以用mktime()。time()+60*60*24*30就是设置 Cookie 30 天后过期。如果设置成零,或者忽略参数, Cookie 会在会话结束时过期(也就是关掉浏览器时)。
你可能注意到了,$expire使用 Unix 时间戳而非Wdy, DD-Mon-YYYY HH:MM:SS GMT这样的日期格式,是因为 PHP 内部作了转换。
Cookie 有效的服务器路径。设置成'/'时,Cookie 对整个域名$domain有效。如果设置成'/foo/', Cookie 仅仅对$domain中/foo/目录及其子目录有效(比如/foo/bar/)。默认值是设置 Cookie 时的当前目录。
$domainCookie 的有效域名/子域名。设置成子域名(例如'www.example.com'),会使 Cookie 对这个子域名和它的三级域名有效(例如 w2.www.example.com)。要让 Cookie 对整个域名有效(包括它的全部子域名),只要设置成域名就可以了(这个例子里是'example.com')。
旧版浏览器仍然在使用废弃的 RFC 2109,需要一个前置的点.来匹配所有子域名。
$secure设置这个 Cookie 是否仅仅通过安全的 HTTPS 连接传给客户端。设置成TRUE
时,只有安全连接存在时才会设置 Cookie。如果是在服务器端处理这个需求,程序员需要仅仅在安全连接上发送此类 Cookie (通过$_SERVER["HTTPS"]判断)。
设置成TRUE
,Cookie 仅可通过 HTTP 协议访问。这意思就是 Cookie 无法通过类似 JavaScript 这样的脚本语言访问。要有效减少 XSS 攻击时的身份窃取行为,可建议用此设置(虽然不是所有浏览器都支持),不过这个说法经常有争议。 PHP 5.2.0 中添加。TRUE
或FALSE
(PHP >=7.3.0)增加的属性。并且在php.ini配置文件中开启session.cookie_samesite选项。
Cookie的SameSite属性用来限制第三方 Cookie,从而减少安全风险。它可以设置三个值。Strict
、Lax
、None
。
Strict
最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。Set-Cookie: CookieName=CookieValue; SameSite=Strict;这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。Lax
规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。Set-Cookie: CookieName=CookieValue; SameSite=Lax;导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。详见下表。
请求类型 示例 正常情况 Lax 链接 发送 Cookie 发送 Cookie 预加载 发送 Cookie 发送 Cookie GET 表单 发送 Cookie 发送 Cookie POST 表单 发送 Cookie 不发送 iframe 发送 Cookie 不发送 AJAX $.get("...")
发送 Cookie 不发送 Image 发送 Cookie 不发送 设置了
Strict
或Lax
以后,基本就杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。None
。Chrome 计划将Lax
变为默认设置。这时,网站可以选择显式关闭SameSite
属性,将其设为None
。不过,前提是必须同时设置Secure
属性(Cookie 只能通过 HTTPS 协议发送),否则无效。设置无效:Set-Cookie: widget_session=abc123; SameSite=None。设置有效:Set-Cookie: widget_session=abc123; SameSite=None; Secure
返回值
如果在调用本函数以前就产生了输出,setcookie()会调用失败并返回FALSE
。如果setcookie()成功运行,返回TRUE
。当然,它的意思并非用户是否已接受 Cookie。
新语法
setcookie (string $name[,string $value= "" [,array $options= [] ]] ) : bool- $options:一个关联数组,它可以有任何密钥expires、path、domain、secure、httponly和samesite。这些值的含义与具有相同名称的参数的含义相同。samesite元素的值应为Lax或Strict。如果未给定任何允许的选项,则它们的默认值与显式参数的默认值相同。如果省略samesite元素,则不设置samesite cookie属性。
setcookie("TestCookie", $value, ['domain' => 'xx.com','expires' =>time()+(60*60*24*30),'samesite' => 'Lax',]);
范例
发送 Cookie 的几个例子:
Example #1setcookie()发送例子
注意:在发送 Cookie 时,值的部分会被自动 urlencode 编码。收到 Cookie 时,会自动解码,并赋值到可变的 Cookie 名称上。如果不想被编码,可以使用setrawcookie()代替——如果你的 PHP 版本是 5 及以上。在脚本里查看我们的测试 Cookie 的内容,使用下面的一个例子:
Example #2setcookie()删除例子
要删除一个 Cookie,应该设置过期时间为过去,以触发浏览器的删除机制。下面的例子展示了如何删除上个例子里的 Cookie:
Example #3setcookie()和数组
通过带 array 标记的 Cookie 名称,也可以把 Cookie 设置成数组。如果有数组元素,可以把它放进 Cookie 里;脚本接收到时,Cookie 名称里的值会是一个数组:
以上例程会输出:
three : cookiethree two : cookietwo one : cookieone
更新日志
版本 | 说明 |
---|---|
5.5.0 | 发送给客户端的 Set-Cookie 头现在会包含 Max-Age 属性。 |
5.2.0 | 添加$httponly参数。 |
注释
Note:要在调用本函数前输出内容,可以使用输出缓冲:让输出的内容在服务器里缓冲起来,直至真正发送给浏览器。可在脚本里调用ob_start()和ob_end_flush(),或设置output_bufferingphp.ini或服务器配置文件里的配置指令。
Note:如果 PHP 指令register_globals设置成on,Cookie 值会自动设置成变量。下面的例子里会存在$TestCookie。我们推荐你使用$_COOKIE。
注意避坑:
- 在页面( Cookie 可见的页面)下次刷新前,Cookie 不会生效。测试 Cookie 是否已经成功设置,需要在下次页面加载时、Cookie 过期前检测。过期时间是通过$expire参数设置的。直接调用print_r($_COOKIE);调试检测 Cookie 是个很好的方式。
- 为同一个参数再次设置 Cookie 前,必须先把它删掉。如果参数的值是空 string 或
FALSE
,并且其他参数和上次调用 setcookie 仍旧一样,则指定的名称会被远程客户端删除。内部的实现是:将值设置成'deleted',并且过期时间是一年前。 - 因为设置值成
FALSE
会导致 Cookie 被删除,所以要避免使用布尔值。代替方式:0是FALSE
,1是TRUE
。 - Cookie 名称可以设置成数组名称,PHP 脚本里会是数组,但用户系统里储存的是单独分开的 Cookie。可以考虑使用explode()为一个 Cookie 设置多个名称和值。不建议将serialize()用于此处,因为它会导致安全漏洞。
多次调用setcookie()会按调用顺序执行。
参见
header()
发送原生 HTTP 头setrawcookie()
发送未经 URL 编码的 cookie- Cookie 章节
- RFC 6265
- RFC 2109
Instead of this: You can this:
Want to remove a cookie? Many people do it the complicated way: setcookie('name', 'content', time() 3600); But why do you make it so complicated and risk it not working, when the client's time is wrong? Why fiddle around with time(); Here's the easiest way to unset a cookie: setcookie('name', 'content', 1); Thats it.
It's worth a mention: you should avoid dots on cookie names.
Note when setting "array cookies" that a separate cookie is set for each element of the array. On high traffic sites, this can substantially increase the size of subsequent HTTP requests from clients (including requests for static content on the same domain). More importantly though, the cookie specification says that browsers need only accept 20 cookies per domain. This limit is increased to 50 by Firefox, and to 30 by Opera, but IE6 and IE7 enforce the limit of 20 cookie per domain. Any cookies beyond this limit will either knock out an older cookie or be ignored/rejected by the browser.
If you're having problem with IE not accepting session cookies this could help: It seems the IE (6, 7, 8 and 9) do not accept the part 'Expire=0' when setting a session cookie. To fix it just don't put any expire at all. The default behavior when the 'Expire' is not set is to set the cookie as a session one. (Firefox doesn't complains, btw.)
something that wasn't made clear to me here and totally confused me for a while was that domain names must contain at least two dots (.), hence 'localhost' is invalid and the browser will refuse to set the cookie! instead for localhost you should use false. to make your code work on both localhost and a proper domain, you can do this:
if you are having problems seeing cookies sometimes or deleting cookies sometimes, despite following the advice below, make sure you are setting the cookie with the domain argument. Set it with the dot before the domain as the examples show: ".example.com". I wasn't specifying the domain, and finally realized I was setting the cookie when the browser url had the http://www.example.com and later trying to delete it when the url didn't have the www. ie. http://example.com. This also caused the page to be unable to find the cookie when the www. wasn't in the domain. (When you add the domain argument to the setcookie code that creates the cookie, make sure you also add it to the code that deletes the cookie.)
Note that at least in PHP 5.5 setcookie() removes previously set cookies with the same name (even if you've set them via header()), so previously fired Set-Cookie headers with e.g. PHPSESSID name are not flushed to the browser. Even headers_list() doesn't see them after session_start(): header("Set-Cookie: PHPSESSID=abc; path=/; domain=.sub.domain.com"); header("Set-Cookie: PHPSESSID=abc; path=/; domain=.domain.com"); print_r(headers_list()); // here you see two Set-Cookie headers with domains for PHPSESSID session_id('abc'); session_start(); print_r(headers_list()); // here you don't; you see only one Set-Cookie produced by session_start()
Of notice, the cookie when set with a zero expire or ommited WILL not expire when the browser closes. What happens is that the browser, when closes the window, if it is a well behaved browser, will delete the cookie from the cookie store. However, the cookie will survive in the server until the garbage collector removes the session, which will happen only when it kicks in and checks the specified session is out of bounds of the setting stated in: http://php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime Please check also: http://php.net/manual/en/session.security.ini.php And in case of doubt, PHP runs on the webserver and has no way whatsoever to interact with a browser apart from receiving requests and answering with responses, so assuming that a cookie will be removed from a browser is just an "hint" for the browser. There is no warranty that such will happen as instructed. That is one of the reasons why the cookie values sent to browsers by some platforms are encrypted and timestamped, to ensure that they are actual and not tampered.
If you want to delete all cookies on your domain, you may want to use the value of: rather than: to dertermine the cookie names. If cookie names are in Array notation, eg: user[username] Then PHP will automatically create a corresponding array in $_COOKIE. Instead use $_SERVER['HTTP_COOKIE'] as it mirrors the actual HTTP Request header.
The server my php code is running on has sessions disabled so I am forced to store a fair bit of arbitrary data in cookies. Using array names was impractical and problematic, so I implemented a splitting routine. I do not serialize any class instances, just arrays and simple objects. In a nutshell, when setting a cookie value, I serialize it, gzcompress it, base64 encode it, break it into pieces and store it as a set of cookies. To fetch the cookie value I get the named piece then iterate through piece names rebuilding the base64 data, then reverse the rest of the process. The only other trick is deleting the pieces correctly. Sessions are better, but if they are not available this is a viable alternative. I chose gz over bz for compression because it looked faster with only slightly worse ratios. Here is a simplified version of my implementation. This is a good starting point but is not suitable for most uses. For example, the domain and path are hard coded and no return values are checked for validity.
Caveat: if you use URL RewriteRules to get stuff like this: domain.com/bla/stuf/etc into parameters, you might run into a hickup when setting cookies. At least in my setup a change in one of the parameters resulted in the cookie not being 'there' anymore. The fix is simple: specify the domain. '/' will usualy do fine.
About the delete part, I found that Firefox only remove the cookie when you submit the same values for all parameters, except the date, which sould be in the past. Submiting blank values didn't work for me. Example : - set - - delete - Jonathan
Note that the $_COOKIE variable not will hold multiple cookies with the same name. It is legitimate to set two cookies with the same name to the same host where the sub domain is different. The next request from the browser will have both cookies in the $_SERVER['HTTP_COOKIE'] variable, but only one of them will be found in the $_COOKIE variable. Requests to subdom.example.com will have both cookies, while browser request to example.com or www.example.com only sends the cookie with the "value1hostonly" value.
You can also delete cookies by supplying setcookie an empty value. setcookie("w3p_cookie", "");
You can use cookies to prevent a browser refresh repeating some action from a form post... (providing the client is cookie enabled!) Hope that helps :) Gareth
#cookies.php /*This code will demonstrate use of cookies with PHP It is very easy to understand and is better for beginner to understand and get idea about power of cookies when used with PHP.Here we give user a form to choose colors he/she likes for website and when he/she visits site again within one hour his/her settings are saved and read from cookie and he/she doesn't have to set the page color and page text color again.You can change time from 3600 seconds to whatever you deem appropriate in your case. if you don't understand anything please email me*/
鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com
图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!