近來php技術群裡有些關於setcookie的討論。
直接進入主題先看看兩段PHP實現COOKIE賦值代碼:
1)setcookie實現:
<?php
setcookie("A", “A_1”, time() + 3600 * 24, '/');
?>
2)header方法實現
<?php
header("Set-Cookie: A=A_1;expires=Thu, 27-Feb-2014 09:38:34 GMT; Max-Age=86400; path=/");
?>
我們來看看setcookie
看源代碼
打開 /php-5.5.8/ext/standard/head.c
找到 PHP_FUNCTION(setcookie) 跳到
PHPAPI int php_setcookie(char *name, int name_len, char *value, int value_len, time_t expires, char *path, int path_len, char *domain, int domain_len, int secure, int url_encode, int httponly TSRMLS_DC)
/*
cookie 名稱不能含有 “=,; trn1314″
*/
...
if (name && strpbrk(name, "=,; \t\r\n\013\014") != NULL) { /* man isspace for \013 and \014 */
zend_error( E_WARNING, "Cookie names cannot contain any of the following '=,; \\t\\r\\n\\013\\014'" );
return FAILURE;
}
...
/*
這段代碼url_encode 默認設置為1 意味著PHP setcookie的方法都會對value進行url_encode處理 。我們在http head的頭部可以看到
*/
這段代碼是刪除一個cookie
<pre>
dt = php_format_date("D, d-M-Y H:i:s T", sizeof("D, d-M-Y H:i:s T")-1, 1, 0 TSRMLS_CC);
snprintf(cookie, len + 100, "Set-Cookie: %s=deleted; expires=%s; Max-Age=0", name, dt);
efree(dt);
上面的代碼可以用來實現
header("Set-Cookie: A=deleted;expires=Thu, 27-Feb-2014 09:38:34 GMT; Max-Age=0; path=/");
PHP COOKIE 的核心參數
設置cookie的存儲路徑 表明cookie的有效路徑
strlcat(cookie, "; path=", len + 100);
strlcat(cookie, path, len + 100);
設置cookie作用域
strlcat(cookie, “; domain=”, len + 100);
strlcat(cookie, domain, len + 100);
如果設置secure為true 意味只能通過https訪問
if (secure) {
strlcat(cookie, "; secure", len + 100);
}
如果設置httponly為true 說明設置的cookie只能被php調用
if (httponly) {
strlcat(cookie, "; httponly", len + 100);
}
將ctr 添加到HEADER裡
result = sapi_header_op(SAPI_HEADER_ADD,&ctr TSRMLS_CC);
打開SAPI.c
SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg TSRMLS_DC)
幾個關鍵的結構體定義:
typedef enum { /* Parameter:*/
SAPI_HEADER_REPLACE, /* sapi_header_line* */
SAPI_HEADER_ADD, /* sapi_header_line* */
SAPI_HEADER_DELETE, /* sapi_header_line* */
SAPI_HEADER_DELETE_ALL, /* void*/
SAPI_HEADER_SET_STATUS /* int */
} sapi_header_op_enum;
typedef struct {
char *header;
uint header_len;
} sapi_header_struct;
typedef struct {
char *line; /* If you allocated this, you need to free it yourself */
uint line_len;
long response_code; /* long due to zend_parse_parameters compatibility */
} sapi_header_line;
找到:
sapi_header_struct sapi_header;
…
/*
將cookie 和 長度加入sapi_header_struct結構體裡
*/
case SAPI_HEADER_ADD:
case SAPI_HEADER_REPLACE:
case SAPI_HEADER_DELETE: {
sapi_header_line *p = arg;
if (!p->line || !p->line_len) {
return FAILURE;
}
header_line = p->line;
header_line_len = p->line_len;
http_response_code = p->response_code;
break;
}
…
sapi_header.header = header_line;
sapi_header.header_len = header_line_len;
上述是PHP處理setcookie的基本步驟.