本文约 4,782 字,预计阅读 12 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:禁了右键,图还是被搬走了
有摄影师给图片站加了”禁止右键”脚本,以为万无一失。结果一周后在某电商详情页看到了自己的图——对方用浏览器开发者工具直接从 Elements 面板复制了图片地址,或者更简单:截图。更让他无奈的是,那张图连水印都没有,因为水印只在详情页的大图上加,列表页的缩略图没有。
这件事说明两个问题:第一,禁右键是”防君子不防小人”的典型,它唯一的真实作用是增加一点点操作门槛;第二,水印必须加在”会被带走的那一版”上,而不是加在你觉得好看的那一版。图片站的版权保护不是靠某一个神奇插件,而是靠一套组合方案:可见水印做声明,隐形标记做溯源,访问控制做拦截,法律手段做兜底。
原理分析:四种保护手段的真实强度
右键/拖拽限制:纯前端,通过监听 contextmenu、dragstart 事件实现。强度几乎为零——禁用 JavaScript、用开发者工具、用截图、用手机长按都能绕过。而且它会影响正常用户(比如想”新标签页打开”的人)。
可见水印:在图片上叠加半透明的文字或图案。强度中等——无法阻止下载,但能阻止”直接使用”。裁剪和抹除需要成本,大多数盗图者会转向没有水印的图。关键是位置与密度:固定在角落的水印容易被裁掉,平铺或位于主体上的水印更难处理。
隐形水印/溯源:在下载时按用户 ID 生成不同的水印或追踪标识,泄露后可定位来源。强度较高,是维权取证的关键。
防盗链与鉴权:通过 referer 校验、签名链接控制访问。强度中等,能拦住大部分”直接引用”。
| 手段 | 阻止下载 | 阻止使用 | 可溯源 | 副作用 |
|---|---|---|---|---|
| 禁右键 | 否 | 否 | 否 | 影响体验 |
| 可见水印 | 否 | 部分 | 弱 | 影响观感 |
| 隐形水印 | 否 | 否 | 强 | 需额外开发 |
| 防盗链 | 部分 | 否 | 否 | 可能误拦 |
保姆级实操
步骤 1:上传时自动生成带水印的版本。 用 wp_generate_attachment_metadata 钩子,在缩略图生成后叠加水印,保留原图。
add_filter( 'wp_generate_attachment_metadata', 'mimangfei_add_watermark', 10, 2 );
function mimangfei_add_watermark( $metadata, $attachment_id ) {
if ( empty( $metadata['sizes'] ) || ! wp_attachment_is_image( $attachment_id ) ) {
return $metadata;
}
$file = get_attached_file( $attachment_id );
if ( ! $file ) {
return $metadata;
}
$editor = wp_get_image_editor( $file );
if ( is_wp_error( $editor ) ) {
return $metadata;
}
$size = $editor->get_size();
$font = get_stylesheet_directory() . '/assets/fonts/SourceHanSans-Regular.otf';
if ( file_exists( $font ) && $size['width'] > 600 ) {
// GD 编辑器支持 GD 专属方法,先做能力探测
if ( method_exists( $editor, 'image' ) ) {
$im = $editor->image;
$white = imagecolorallocatealpha( $im, 255, 255, 255, 90 );
$font_size = max( 14, (int) ( $size['width'] / 40 ) );
$text = '© mimangfei.com';
$box = imagettfbbox( $font_size, 0, $font, $text );
$x = (int) ( $size['width'] - ( $box[2] - $box[0] ) - 20 );
$y = (int) ( $size['height'] - 20 );
imagettftext( $im, $font_size, 0, $x, $y, $white, $font, $text );
}
}
$editor->save( $file );
return $metadata;
}
步骤 2:只给大图加水印,列表图保持干净。 用尺寸判断控制作用范围,兼顾观感与保护。
function mimangfei_watermark_target_sizes( $metadata ) {
$targets = array( 'gallery_large', 'full' );
$result = array();
foreach ( $targets as $t ) {
if ( isset( $metadata['sizes'][ $t ] ) ) {
$result[] = $metadata['sizes'][ $t ]['file'];
}
}
return $result;
}
步骤 3:配置防盗链。 拦住直接引用,但放行搜索引擎与正常来源。
location ~* \.(?:jpg|jpeg|png|webp)$ {
valid_referers none blocked server_names
*.mimangfei.com
*.baidu.com *.google.com *.bing.com;
if ($invalid_referer) {
# 返回带水印的占位图,而不是硬 403
rewrite ^ /watermarked-placeholder.jpg last;
}
expires 30d;
}
# 限制单 IP 请求频率,缓解批量抓取
limit_req_zone $binary_remote_addr zone=imgzone:10m rate=30r/s;
location /wp-content/uploads/ {
limit_req zone=imgzone burst=60 nodelay;
}
步骤 4:加”防君子”的前端限制。 明确告诉自己这只是门槛,不是防护。
document.addEventListener( 'contextmenu', function ( e ) {
if ( e.target.closest( '.gallery-masonry__item' ) ) {
e.preventDefault();
}
} );
document.addEventListener( 'dragstart', function ( e ) {
if ( e.target.tagName === 'IMG' ) {
e.preventDefault();
}
} );
步骤 5:给下载用户生成可溯源的标识。 记录用户 ID 与时间戳,泄露后可定位。
function mimangfei_download_token( $user_id, $post_id ) {
$payload = $user_id . '|' . $post_id . '|' . time();
$token = hash_hmac( 'sha256', $payload, wp_salt( 'auth' ) );
return substr( $token, 0, 16 ) . '-' . base64_encode( $payload );
}
function mimangfei_parse_token( $token ) {
$parts = explode( '-', $token );
if ( 2 !== count( $parts ) ) {
return false;
}
$payload = base64_decode( $parts[1], true );
if ( ! $payload ) {
return false;
}
list( $uid, $pid, $time ) = array_pad( explode( '|', $payload ), 3, 0 );
return array(
'user_id' => (int) $uid,
'post_id' => (int) $pid,
'time' => (int) $time,
);
}
步骤 6:版权声明与取证。 在页面放明确的版权声明,发现侵权时用可信时间戳或区块链存证平台固定证据,再发函或起诉。水印和访问日志是核心证据。
常见踩坑
- 以为禁了右键就安全,实际开发者工具一秒破。
- 只给详情页大图加水印,缩略图没加,被盗的恰恰是缩略图。
- 水印固定在右下角,被裁剪掉就毫无痕迹。
- 水印透明度太高(alpha > 100),去水印工具一键抹除。
- 防盗链把搜索引擎也拦了,图片搜索流量全丢。
- 案例:某图库站发现自己的图片被批量搬运到海外站点。由于当初只在详情页加了浅色水印,搬运方直接取了列表页的 800px 缩略图,画面干净可用。事后改造:所有超过 400px 的派生尺寸统一烧入半透明平铺水印,下载接口为会员生成带 ID 的隐形标记。三个月后再次发现泄露时,通过标记直接定位到了泄露账号,完成了取证。
- 加水印时直接覆盖原图,想恢复原图时才发现没有备份。
- 用 GD 的
imagettftext()但字体路径写错,报 “Could not find/open font”,水印静默失败。
总结
保护是否到位,用一个问题判断:如果这张图被搬到别的站点,我能不能证明它是我的?能证明(水印 + 溯源标记 + 日志),说明方案有效;不能,说明只做了表面功夫。行动清单:① 所有对外可见尺寸统一烧入水印;② 水印平铺或压在主体上,不固定在角落;③ 防盗链放行搜索引擎与空来源;④ 下载带用户级溯源标识;⑤ 保留未加水印的原图;⑥ 侵权时先存证再交涉。图片站的存储与展示环节见 WordPress 图片素材站搭建、资源站文件存储与流量成本 与 WordPress 图片优化。
