PHP 设置响应头
本文最后更新于:2024年3月18日 凌晨
PHP 设置响应头
- 正如我们前面所讨论的,服务器发送回来的HTTP响应包含以下信息:用于识别响应主体内容的头(header),发送响应的服务器,响应消息有多少字节和响应何时发出等等,PHP和Apache通常已经为你处理好了头信息,将文档识别为HTML和计算HTML页面的长度等等,绝大多数WEB程序不需要自己设置头,然而,如果你想让服务器返回的不是HTML,或者想设置页面的过期时间,重定向客户端浏览器到另一个地址,或是产生一个特定的HTTP错误,就需要使用
header()
函数来设置头部。
- 设置header一定要在生成主体内容之前完成,这意味着所有
header()
(或setcookie()
,如果你想设置 cookie)要在文件的最前面,甚至在<html>
标签之前,例如:
1 2 3 4 5 6 7 8 9 10
| <?php header('Content-Type: text/plain'); ?>
Date:today From:fred To:barney Subject:hands off! My lunchbox is mine and mine alone.Get your own, you filthy scrounger!
|
1
| Warning: Cannot add header information - headers already sent
|
不同的内容类型
- Content-Type头指出了被返回的文档的类型,它通常是"text/html",指明了它是一个HTML文档,但还有其他一些有用的文档类型,例如"text/plain"让浏览器强制性地将内容当作纯文本来处理,这个类型就类似于自动的"查看源代码",它在调试时很有用。
重定向
- 你可以向浏览器发送一个新的URL,并让浏览器转向到这个地址,这样的重定向(redirection)操作,只需要通过设置Location头即可:
1 2 3 4
| <?php header('Location: http://www,example.com/elsewhere.html'); exit(); ?>
|
- 如果你只提供相对的URL(如"/elsewhere.hmtl").重定向会在服务器内部进行,这种方法很少用,因为浏览器并不知道它得到的页面是否是所请求的,如果在新的文档中存在相对URL,浏览器会将它们解释成相对于所请求的文档,而不是被发送的文档,一般来说,我们习惯于重定向到绝对URL
过期
- 服务器可以显式地通知浏览器(或者那些存在于服务器和浏览器发之间的代理服务器缓存)文档的过期时间,代理服务器和浏览器缓存在过期之前可保持文件,或提前结束它,重新载入一个被缓存的页面不需要和服务器进行通讯,但是尝试获取一个已经过期的文档就需要和服务器联系了。
- 为一个文档设置过期时间,可使用Expires头:
1
| header('Expires: Fri, 18 Jan 2006 05:30:00 GMT');
|
- 要使文档在页面生成后的3小时后过期,我们使用
time()
和gmstrftime()
函数生成过期日期字符串:
1 2 3
| $now = time(); $then = gmstrftime("%a, %d %b %Y %H:%M:%S GMT",$now+60*60*3); header("Expires:$then");
|
1 2 3
| $now = time(); $then = gmstrftime("%a, %d %b %Y %H:%M:%S GMT",$now+365*86440); header("Expires:$then");
|
1 2
| $then = gmstrftime("%a, %d %b %Y %H:%M:%S GMT"); header("Expires:$then");
|
- 以下是不使浏览器或代理缓存保存你的文档的最好方法;
1 2 3 4 5
| header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified:" . gmdate("D,d M Y H:i:s") . " GMT"); header("Cache-Control: no-store,no-cache,must-revalidate"); header("Cache-Control: post-check=0,pre-check=0",false); header("Pragma: no-cache");
|
- 你可以在Duane Wessels所著的$Web Caching$一书(由O’Reilly出版)的第6章中找到有关控制浏览器和Web缓存行为的更多信息。
HTTP认证
- HTTP认证(HTTP authentication)通过请求的header和响应状态来工作,浏览器可以将用户名和密码放在请求的头里发送,如果认证凭证(credential,即指用户名和密码)未发送或者不匹配,服务器将发送一个"401 Unauthorized"响应并通过WWW认证头来确定当前认证的区域(realm)(一个字符串,诸如"Mary’s Pictures”或"Your Shopping Cart"),这通常会导致浏览器弹出一个"Enter username and password for …"对话框,且该页面会重新请求更新头中的认证凭证。
- 为了用PHP来处理认证,可检查用户名和密码($_SERVER数组中的PHP_AUTH_USER和PHP_AUTH_PW两个元素)并调用
header()
函数来设置区域,然后发送一个"401 Unauthorized"响应:
1 2
| header('WWW-Authenticate: Basic realm="Top Secret Files"'); header("HTTP/1.0 401 Unauthorized");
|
- 可以使用各种方法来验证用户名和密码,例如:查询数据库,或读一个保存着合法用户名的文件,或者查询一个Microsoft域服务器。
- 下例检查密码是否为翻转的用户名:
1 2 3 4 5 6 7 8 9 10
| $auth_ok = 0; $user = $_SERVER['PHP_AUTH_USER']; $pass = $_SERVER['PHP_AUTH_PW']; if(isset($user) && isset($pass) && $user === strrev($pass)){ $auth_ok = 1; } if(!$auth_ok){ header('WWW-Authenticate: Basic realm="Top Secret Files"'); header('HTTP/1.0 401 Unauthorized'); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php $auth_ok = 0; $user = $_SERVER['PHP_AUTH_USER']; $pass = $_SERVER['PHP_AUTH_PW']; if(isset($user) && isset($pass) && $user === strrev($pass)){ $auth_ok = 1; } if(!$auth_ok){ header('WWW-Authenticate: Basic realm="Top Secret Files"'); header('HTTP/1.0 401 Unauthorized'); // 如果用户点击"Cancel"按钮,就只能看到在此输出的信息。 exit; } ?> }<!-- your password-protected document goes here -->
|
- 如果你要保护的页面不只一个,把以上代码放到一个独立的文件中,然后再每个需要的页面include进来。
- 如果你的服务器使用CGI版本的PHP,而不是Apache模块方式,以上这些变量无法使用,你需要采用其他形式的认证,例如通过HTML表单来获得用户名和密码。