百科

php显示加密图片地址并且能在页面显示

时间:2010-12-5 17:23:32  作者:知识   来源:综合  查看:  评论:0
内容摘要:图片被直接扒走,是很多站长都遇到过的事。你辛辛苦苦拍的图、做的设计,别人一个右键另存为就变成他的了。更气人的是,有些采集程序专门盯着图片URL批量下载。把真实图片地址藏起来,让浏览器通过PHP中转输出

图片被直接扒走,显显示是示加很多站长都遇到过的事。你辛辛苦苦拍的密图图、做的片地设计,别人一个右键另存为就变成他的址并了。更气人的页面是,有些采集程序专门盯着图片URL批量下载。显显示把真实图片地址藏起来,示加让浏览器通过PHP中转输出,密图这招能挡住大部分低级爬虫和普通用户的片地直接下载。

原理不复杂。址并页面上显示的页面<img src="show.php?id=123">,这个show.php接收id参数,显显示去数据库或某个映射表里查出真实文件路径,示加然后读取文件内容,密图设置正确的Content-Type头,把二进制数据吐给浏览器。浏览器拿到的是图片,但它看到的地址永远是show.php?id=123,不知道真实文件在哪。

先看一个最简实现:

<?php $id = intval($_GET['id']); // 假设用数组模拟映射,实际项目里换成数据库查询 $map = [ 1 => '/uploads/2024/photo1.jpg', 2 => '/uploads/2024/photo2.png', 3 => '/uploads/2024/design.webp', ]; if (!isset($map[$id])) {  http_response_code(404); exit; } $file = $map[$id]; if (!file_exists($file)) {  http_response_code(404); exit; } $info = getimagesize($file); if ($info === false) {  http_response_code(403); exit; } header('Content-Type: ' . $info['mime']); header('Content-Length: ' . filesize($file)); header('Cache-Control: public, max-age=86400'); readfile($file); exit; 

这段代码干了三件事:验证id合法性、确认文件确实是图片、输出内容。getimagesize那步别省,有人会把.php文件改成.jpg后缀传上来,不加验证等于给自己挖坑。

页面端调用就很简单了:

<img src="show.php?id=1" alt="示例图片"> <img src="show.php?id=2" alt="另一张图"> 

实际项目里,id通常不是连续的1、2、3。我会给每张图生成一个随机字符串作为token,比如a3f8c2e1d9,存到数据库里对应真实路径。这样别人猜不到其他图片的地址,爬虫也没法遍历。改成show.php?token=a3f8c2e1d9,查询时用token查路径。

有个细节容易忽略:大图片用readfile直接输出会占用PHP内存。如果图片几十MB,并发一高服务器就扛不住。解决办法是用fpassthru配合fopen,或者干脆用Nginx的X-Accel-Redirect让Nginx来发文件,PHP只负责鉴权。小站用readfile够了,日PV上万的站点建议走X-Accel-Redirect方案。

还有缓存问题。每次请求都过PHP,图片多了服务器压力不小。我给响应加了Cache-Control: public, max-age=86400,浏览器一天内不会重复请求。如果图片内容会变,可以用ETag或Last-Modified做协商缓存,减少传输量。

防盗链也可以在这个环节加上。检查$_SERVER['HTTP_REFERER']是不是来自自己站点,不是就返回一张警告图或者直接403。不过这招对伪造Referer的爬虫没用,只能防住普通站外引用。

说个实际踩过的坑。有次部署到新服务器,图片全部显示裂图。查了半天发现是show.php文件本身带了BOM头,输出图片二进制之前先输出了三个字节的BOM,导致图片数据被污染。解决办法是确保PHP文件保存为无BOM的UTF-8格式。这种问题不遇到根本想不到。

另外注意header('Content-Type')之前不能有任何输出,包括空格和换行。有人喜欢在<?php前面留空行,或者?>后面加空格,都会导致header失效。纯PHP文件建议省略结尾的?>。

这套方案挡不住 determined 的人——他可以直接访问服务器文件系统,或者用浏览器开发者工具看网络请求。但对于99%的普通用户和低级采集脚本,已经够用了。图片保护本来就是提高门槛,不是绝对防御。

如果图片涉及付费内容,光藏地址不够,还得加用户鉴权。在show.php里判断session或token,没登录或没购买就不输出图片。这才是真正有价值的场景——不是防下载,是控制访问权限。

最近更新
热门排行
copyright © 2026 powered by 力不从心网   sitemap