探索饼干的世界:初学者指南
您可能听说过 cookie,但它们到底是什么以及我们实际上可以用它们做什么?在本教程中,我们将重点介绍 cookie 的基础知识,并了解它们在各种 Web 应用程序和站点环境中的功能。我们还将学习如何在 PHP 和 JavaScript 项目中使用它们,同时特别注意使用它们时可能出现的安全问题。阅读本文后,您将获得在您自己的 Web 应用程序中安全实施 cookie 所需的技能。
第 1 步.了解 Cookie
我们旅程的第一步是发现这些 cookie 到底是什么!即使您已经使用过他们,您可能仍然会发现这部分非常有用 – 所以请继续关注我!
摘要
您可以很容易地将 Cookie 视为保存到您计算机上的文本文件。根据网络服务器的请求,您的浏览器会创建这样的文件。发生这种情况后,网络服务器可以从此文件读取内容或向该文件写入内容。尽管这看起来是一项危险的功能 – 毕竟没有人喜欢其他人向他们的计算机写入文件,但有一些限制可以使此过程尽可能安全。
- Web 服务器只能访问设置到其自己域的 cookie。该域是当Web服务器请求新的cookie时由浏览器设置的,并且只能是Web服务器的域或子域(Web服务器可以根据需要选择子域)。这意味着 mozilla.com 无法读取 google.com 等设置的 Cookie,反之亦然。
- 根据 HTTP 协议,每个 Cookie 不能大于 4096 字节 (4KB)。
- 每个域的 Cookie 数量有限制。每个浏览器的数量有所不同,但通常使用的限制是 20 个 cookie。这是为了防止单个域占用客户端的磁盘空间。
- 客户端硬盘上的 Cookie 总数有限制。每个浏览器的这个数字也不同,但通常限制在三百个左右。当超过这个数字时,旧的 cookie 将被删除,然后再创建新的 cookie。
Cookie 有有效期。设置此日期是为了当网络服务器不再需要旧的 cookie 时,浏览器可以删除它们。如果过期日期为空,则当与服务器的连接关闭时,cookie 将被删除。当用户关闭网站的窗口或选项卡,或者用户关闭整个浏览器时,就会发生这种情况。这些 cookie,有时称为会话 cookie,主要用于存储临时设置。
技术
让我们看看这些东西在技术层面上是什么样子的。 Cookie 通过 HTTP 协议传输。这是浏览器用来检索文件并将文件发送到服务器的协议。请求 cookie 后,每次浏览器获取网页上的新项目时,都会将 cookie 发送到服务器。下面,我们可以看到服务器请求新 cookie 的片段(此片段是 HTTP 响应的一部分)。
Set-Cookie: Name=content data; expires=Fri, 31-Dec-2010 23:59:59 GMT; path=/; domain=.example.net
登录后复制
现在不要害怕,这一切都很容易理解!
- Set-Cookie:是让浏览器知道服务器想要创建一个新的cookie。
- 名称是cookie的名称。域中的每个 cookie 必须有不同的名称,以便浏览器可以将所有 cookie 分开。名称后面是 =内容数据,其中“内容数据”是要包含在 cookie 中的数据。该数据可以是文本字符串或数字,并且如上所述,大小最大可达 4KB。
- expires= 是到期日期的命令。到期日期采用“Wdy,DD-Mon-YYYY HH:MM:SS GMT”格式(不要问我为什么将其定义为这种荒谬的格式,因为我也不知道。没有用户看到过过期日期,那么为什么要在长日期上浪费内存、硬盘空间和带宽呢?)。不过不用担心,因为大多数编程语言都有易于使用的功能可供您使用。浏览器会自动删除过期日期已过的 cookie。
- 域和路径需要一些更深入的解释。 域是cookie将在其中处于活动状态的域。如果域是“ads.google.com”,则 Cookie 将仅发送到该域的服务器,如果域是“google.com”,则 Cookie 将发送到该域的任何子域的任何服务器Google,包括 google.com 本身。
- 路径是 cookie 发送到的域的路径。这意味着,如果路径设置为“/images/”且域设置为“ads.google.com”,则只有浏览器从“ads.google”请求文件时,Cookie 才会发送到服务器.com/images/’。如果路径设置为“/”,则无论请求的文件在服务器上的位置如何,cookie都会发送到服务器。
在下一步中,我们将回顾如何在编程语言中使用这些属性。
步骤 2. 如何创建和读取 Cookie
可以通过多种方式创建 Cookie,但是,出于本教程的目的,我们将重点关注 PHP 和 JavaScript。
PHP
在 PHP 中创建 cookie 时要记住的最重要的事情是,您必须在向浏览器发送任何数据之前设置所有 cookie。这意味着您应该始终在任何输出之前初始化新的cookie。这包括 echo() 或 print() 命令以及 或
标记。当然,也有一些例外,但这是一般的经验法则。
<?php /***Creating a cookie***/ $name = 'clientname'; $value = 'Peter Griffin'; //time() gives current time in seconds, and we add 60 seconds * 30 = 30 minutes //so this cookie expires in 30 minutes. //You may notice that the expire date is in seconds, PHP translates this to //the correct format internally! $expireDate = time() + 60 * 30; $path = '/example/'; $domain = 'test.envato.com'; $secure = false; //only transmit the cookie if a HTTPS connection is established $httponly = true; //make cookie available only for the HTTP protocol (and not for JavaScript) setcookie( $name, $value, $expireDate, $path, $domain, $secure, $httponly); <html> .... //all content etc goes here ?>
登录后复制
除了 $secure 和 $httponly 之外,现在看起来应该很熟悉。 “secure”是强制仅在已建立 HTTPS 连接的情况下发送 cookie,如果设置为 true,则通常应设置为 false。 “httponly”使 cookie 只能通过 HTTP 协议使用,这意味着客户端语言(如 JavaScript 和 VBscript)无法访问 cookie。这有助于防止令人讨厌的事情,例如跨站点脚本,如果您无意使用 JavaScript 等语言编辑客户端的 cookie,则应将其设置为 true。另外,为了防止误解,“httponly”并不意味着 cookie 不能通过 HTTPS 发送,因为事实上它们仍然可以。但是,请注意,上面的代码片段可以变得非常小(并且应该如此):
<?php setcookie( 'clientname', 'Peter Griffin', time()+60*30, '/example/', 'test.envato.com', false,true); ?>
登录后复制
太棒了!现在我们可以创建cookie,但我们也必须能够读取它们。幸运的是,一旦创建了 cookie,PHP 就可以让这一切变得非常简单。在 PHP 中,有一个名为 $_COOKIE[] 的环境变量,可用于提取 cookie 的值。要使用它,只需将 cookie 的名称插入方括号 [] 内,如下所示:
<?php $cookieValue = $_COOKIE['name of the cookie']; ?>
登录后复制
这个环境变量可以像其他环境变量一样使用。就像 $_GET[] 和 $_POST[] 一样,如果您愿意,可以直接将其视为普通变量(当然,一旦您检查了 cookie 是否确实存在)。
如果您想更改过期日期、路径或域,则必须使用与原始 cookie 相同的名称,使用 setcookie() 覆盖现有 cookie。如果您将过期日期更改为过去的日期(例如 time()-30*60),则 Cookie 将被删除。
JavaScript
Cookie 也可以在客户端读取和写入。尽管 JavaScript 没有提供一个很好的读取和写入 cookie 的解决方案,但它是可能的并且被广泛使用。 JavaScript 使用 document.cookie 对象进行 cookie 操作,如以下代码片段所示:
//get current date var expiredate = new Date(); //increase date by 5 hours expiredate.setHours( expiredate.getHours() + 5); document.cookie = 'cookiename=cookievalue; expires=' + expiredate.toUTCString() + 'path=/example/; domain=test.envato.com';
登录后复制
您可能已经注意到,此语法与 HTTP 协议表示法非常相似。这样做的优点是更容易控制,但也带来了一些潜在的问题。下面是读取 cookie 的 片段。
var cookieName = 'testcookiename'; var textArray = document.cookie.split(';'); //put all the parts of the string in an array for(var i = 0; i < textArray.length; i++){ // loop though all string pieces var textPiece = textArray[i]; //contains 1 string piece //filter beginning spaces while(textPiece(0)==' ') textPiece = textPiece.substring(1,textPiece.length); //if the textpiece contains our cookies name if (textPiece.indexOf(cookieName)== 0){ //return whats after the cookies name return textPiece.substring(cookieName.length,c.length); } }
登录后复制
我知道,我知道;这是一种痛苦。对你们来说幸运的是,我在下面发布了一些预先编写的函数(不过,出于学习目的,您可能想创建自己的函数,而且您应该这样做!)。
function writeCookie(cookieName, cookieValue, expireHours, path, domain){ var date = new Date(); date.setHours(date.getHours + expireHours); document.cookie = cookieName + '=' + cookieValue + '; expires=' + date + '; path=' + path + '; domain=' + domain; } function readCookie(cookieName){ var textArray = document.cookie.split(';'); for(var i = 0; i < textArray.length; i++){ var textPiece = textArray[i]; while(textPiece(0)==' ') textPiece = textPiece.substring(1,textPiece.length); if (textPiece.indexOf(cookieName)== 0) return textPiece.substring(cookieName.length,c.length); } }
登录后复制
请记住,这些片段不包含任何错误检查。
第 3 步. 如何处理 Cookie
你知道吗? –
Cookie 是由 Netscape 发明的,该公司希望使用它们为在线商店创建购物车。多亏了 cookie,人们即使在与商店断开连接后也能够保留购物车中的商品。
如今,我们几乎将 Cookie 用于您能想到的所有用途。您可以使用它们来保存用户设置,例如名称、语言、位置或屏幕尺寸。这可以提高您想要为客户提供的服务质量,因为您可以优化为客户提供的服务,并在将来记住这种优化。例如,您可以将客户的首选语言保存到 cookie,然后在客户每次访问您的网站时以首选语言显示您网站的内容。
当然,用cookie还有很多比这更有趣的事情!在下一步中,我将向您展示一个很酷的代码片段示例。
第 4 步。 编写很酷的东西
终于!现在我们可以开始编写一些很棒的代码了!下面是一个奖励片段,它使用 cookie 创建重新登录机制。
“记住我”登录片段
在我们开始之前,此片段包含一些 MySQL 代码。如果您不熟悉 MySQL,请不要惊慌。尽管这段代码有点困难,但只要有一些基本的 PHP 和 cookie 知识就应该可以理解。
要创建“记住我”的实现,我们必须具备一些条件。首先,我们需要一个包含用户名、密码和标识字段的数据库表。其次,我们需要一个唯一的字符串或数字来通过cookie安全地识别客户端(这是数据库表中的标识)。在此代码片段中,我们将使用 SHA-1 摘要(它只是一个字符串)作为标识符。如果使用得当,这可以提供出色的安全性。
大多数人只是在 cookie 中插入用户名和密码,然后自动将其发送到服务器。 应始终避免这种情况!Cookie 通常通过非安全连接发送,因此任何潜在攻击者很容易看到内容。
<?php //this assumes that the user has just logged in /****Creating an identification string****/ $username; //normally the username would be known after login //create a digest from two random values and the username $digest = sha1(strval(rand(0,microtime(true)) + $username + strval(microtime(true)); //save to database (assuming connection is already made) mysql_query('UPDATE users SET reloginDigest="'.$digest.'" WHERE username="'.$username.'"'); //set the cookie setcookie( 'reloginID', $digest, time()+60*60*24*7,'/', 'test.example.com', false, true); //this assumes that the user is logged out and cookie is set /****Verifying users through the cookie****/ $digest = $_COOKIE['reloginID']; $digest = mysql_real_escape_string($digest); //filter any malicious content //check database for digest $result = mysql_query('SELECT username FROM users WHERE reloginDigest="'.$digest.'"'); //check if a digest was found if(mysql_num_rows($result) == 1){ $userdata = mysql_fetch_object($result); $username = $userdata->username; //here you should set a new digest for the next relogin using the above code! echo 'You have successfully logged in, '.$username; } else{ //digest didn't exist (or more of the same digests were found, but that's not going to happen) echo "failed to login!"; } ?>
登录后复制
通过像我们一样使用摘要,获得两个相同摘要的机会微乎其微。摘要是一个四十个字符串,理论上,如果输入发生更改,它应该始终提供完整的随机输出。实际上,您应该在服务器端代码中添加时间限制,以便摘要在 X 分钟后无效。这可以防止攻击者复制某人的 cookie 并使用它们登录。
第 5 步。最佳实践
本教程即将结束。作为结论,我想总结一些最佳实践:
- 切勿将敏感数据插入 cookie。客户可能会在公共计算机上浏览,因此不要留下任何个人信息。
- 永远不要相信来自 Cookie 的数据。始终过滤字符串和数字!攻击者可能会向 Cookie 写入恶意数据,以执行您不希望服务执行的操作。
- 尝试估计 cookie 的有效期限,并相应地设置到期日期。您不想让客户的计算机被设置为一百年后过期的旧 cookie 占用。
- 始终设置 secure 和 httponly 以满足您的应用程序需求。如果您的应用程序不使用 JavaScript 编辑 cookie,请启用 httponly。如果您始终有 HTTPS 连接,请启用安全。这提高了数据的完整性和机密性。
结论
我希望您从今天的 Nettuts+ 教程中学到了一些东西。如果您有任何疑问,请随时发表评论或在 Twitter 上打个招呼。
以上就是探索饼干的世界:初学者指南的详细内容,更多请关注php中文网其它相关文章!