You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Django Rest Framework+AWS环境下,如何禁止用户复制下载按钮链接?

解决方案:禁用下载按钮的右键「复制链接地址」功能

一、React前端快速实现方案

前端防护属于临时表层措施,能挡住普通用户,但懂技术的仍可通过抓包绕过,不过满足你交付紧迫的需求没问题。以下是两种可行实现方式:

方案1:用按钮模拟下载(彻底避免右键复制链接)

不用<a>标签,改用按钮触发下载请求,同时阻止右键菜单弹出:

import React from 'react';

const DownloadButton = () => {
  // 点击按钮时获取临时下载链接并触发下载
  const handleDownload = async () => {
    try {
      // 调用DRF接口获取AWS文件的临时访问链接
      const response = await fetch('/api/get-download-url/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          // 有用户认证的话加上token
          'Authorization': `Token ${localStorage.getItem('authToken')}`
        },
        body: JSON.stringify({ file_id: '目标文件ID' })
      });
      const data = await response.json();
      
      // 创建隐藏a标签触发下载
      const downloadLink = document.createElement('a');
      downloadLink.href = data.download_url;
      downloadLink.download = data.file_name;
      document.body.appendChild(downloadLink);
      downloadLink.click();
      document.body.removeChild(downloadLink);
    } catch (err) {
      console.error('下载失败:', err);
    }
  };

  // 阻止右键菜单弹出
  const blockRightClick = (e) => e.preventDefault();

  return (
    <button 
      onClick={handleDownload}
      onContextMenu={blockRightClick}
      style={{ padding: '8px 16px', cursor: 'pointer' }}
    >
      下载文件
    </button>
  );
};

export default DownloadButton;

方案2:改造<a>标签(保留链接样式)

如果必须用<a>标签的样式,可通过动态赋值链接+阻止右键实现:

import React from 'react';

const DownloadLink = () => {
  // 点击时才获取真实链接并跳转下载
  const handleClick = async (e) => {
    e.preventDefault();
    try {
      const response = await fetch('/api/get-download-url/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Token ${localStorage.getItem('authToken')}`
        },
        body: JSON.stringify({ file_id: '目标文件ID' })
      });
      const data = await response.json();
      window.open(data.download_url, '_blank');
    } catch (err) {
      console.error('获取下载链接失败:', err);
    }
  };

  const blockRightClick = (e) => e.preventDefault();

  return (
    <a 
      href="#"
      onClick={handleClick}
      onContextMenu={blockRightClick}
      style={{ padding: '8px 16px', cursor: 'pointer', color: '#0066cc', textDecoration: 'none' }}
    >
      下载文件
    </a>
  );
};

export default DownloadLink;

二、长期安全补全建议(交付后尽快做)

前端防护不是万全之策,因为用户可通过开发者工具抓包、禁用JS绕过。结合你的AWS环境,必须做以下优化:

  • 开启AWS S3预签名URL:通过DRF生成带有效期的临时链接,即使被分享,过期后也无法访问
  • 关闭S3桶的公网访问权限,配置桶策略/ACL,仅允许通过DRF服务访问
  • 在DRF接口中添加用户权限校验,确保只有授权用户能获取下载链接

三、DRF端生成预签名URL的示例

配合前端使用,生成限时有效的S3文件访问链接:

from django.http import JsonResponse
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
import boto3
from botocore.config import Config
from datetime import timedelta

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def get_download_url(request):
    file_id = request.data.get('file_id')
    # 从数据库获取对应文件的S3存储键
    # file_obj = FileModel.objects.get(id=file_id)
    s3_file_key = '存储桶内的文件路径/文件名.pdf'

    # 初始化S3客户端
    s3_client = boto3.client(
        's3',
        aws_access_key_id='你的AWS Access Key',
        aws_secret_access_key='你的AWS Secret Key',
        config=Config(signature_version='s3v4')
    )

    # 生成15分钟有效期的预签名URL
    presigned_url = s3_client.generate_presigned_url(
        'get_object',
        Params={'Bucket': '你的S3桶名', 'Key': s3_file_key},
        ExpiresIn=900  # 单位:秒
    )

    return JsonResponse({
        'download_url': presigned_url,
        'file_name': '显示给用户的文件名.pdf'
    })

内容的提问来源于stack exchange,提问作者Sarthak Bhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 21:12:52