Điểm:1

Có thể cho phép người dùng ẩn danh xem tệp được quản lý tạm thời qua hook_file_download() không?

lá cờ ng

Tôi đang tạo hệ thống xem trước hình ảnh trực tiếp cho các sản phẩm có thể tùy chỉnh cần gửi tệp tạm thời của người dùng đến máy chủ từ xa.

Tôi có một hệ thống dựa trên mã thông báo để bảo vệ tệp nhưng có vẻ như vấn đề là tệp chỉ là tạm thời. Tôi đã tạo hook_file_download() để trả lại các tiêu đề theo yêu cầu để cho phép truy cập khi được phê duyệt nhưng quyền truy cập tệp vẫn bị từ chối ở đâu đó.

Có vẻ như đây không phải là vấn đề về trọng lượng của mô-đun vì tôi đã làm cho mô-đun tùy chỉnh của mình có trọng lượng thấp nhất và được xác minh thông qua mã gỡ lỗi mà nó kích hoạt sau lõi file_file_download()

CHỈNH SỬA: Khắc phục sự cố khác cho thấy mảng tiêu đề đang nhận giá trị khóa được đặt thành "-1" ở đâu đó sau hook_file_download() và lõi "FileDownloadController" là nơi tệp bị từ chối. Bất kỳ ý tưởng nào khi giá trị tiêu đề [0] = -1 này đang được đặt và cách ghi đè giá trị đó?

Nếu tôi loại bỏ nó xuống những điều cơ bản để kiểm tra như được hiển thị bên dưới, các tiêu đề 'cho phép' được trả lại nhưng tệp vẫn bị chặn khi được xem từ một trình duyệt ẩn danh:

hàm MYMODULE_file_download($uri) {

  // Kiểm tra xem đây có phải là bản tải xuống cấu hình không.
  $scheme = StreamWrapperManager::getScheme($uri);

  if ($scheme == 'tạm thời'){
    if ($files = \Drupal::entityTypeManager()->getStorage('file')->loadByProperties(['uri' => $uri])){

      $file = đặt lại($files) ?: NULL;
      
      // Quyền truy cập được cấp.
      $headers = file_get_content_headers($file);
      trả lại tiêu đề $;
    }
  }
}
Điểm:1
lá cờ us

Các tập tin tạm thời được xử lý bởi file_file_download(), một triển khai của hook_file_download() được thực hiện từ mô-đun Tệp. Mã nó sử dụng là mã sau đây.

  // Tìm hiểu xem một tệp tạm thời có còn được sử dụng trong hệ thống hay không.
  nếu ($file->isTemporary()) {
    $usage = \Drupal::service('file.usage')->listUsage($file);
    if (empty($usage) && $file->getOwnerId() != \Drupal::currentUser()
      ->id()) {
      // Từ chối quyền truy cập vào các tệp tạm thời không sử dụng mà không thuộc sở hữu của
      // cùng một người dùng. Điều này ngăn chặn sự cố bảo mật mà một tệp riêng tư
      // được bảo vệ bởi các quyền của trường sẽ khả dụng sau khi sử dụng
      // đã bị xóa và trước khi nó thực sự bị xóa khỏi hệ thống tệp.
      // Các mô-đun phụ thuộc vào hành vi này sẽ làm cho tệp trở nên vĩnh viễn
      // thay thế.
      trả về -1;
    }
  }

Việc đọc các nhận xét được thực hiện nhằm mục đích tránh tệp riêng tư, được bảo vệ bởi quyền của trường, hiển thị sau khi quyền của trường được thay đổi nhưng trước khi tệp bị xóa.

Nhìn vào mã gọi hook đó, trong FileDownloadController::download() ví dụ: tôi không thấy cách nào để tránh điều đó, vì mã không sử dụng hook_file_download_alter().

Một giải pháp thay thế có thể là đặt tệp đó là đang được sử dụng vì mã kiểm tra tệp không được sử dụng trước khi chặn quyền truy cập.

hàm mymodule_file_download($uri) {
  if (StreamWrapperManager::getScheme($uri) == 'tạm thời') {
    if ($files = \Drupal::entityTypeManager()->getStorage('file')->loadByProperties(['uri' => $uri])){
      nếu ($file = reset($files)) {
        // Quyền truy cập được cấp.
        \Drupal::service('file.usage')->add($file, 'mymodule', 'uncurrent_entity', 10);
        $headers = file_get_content_headers($file);
        trả lại tiêu đề $;
      }
    }
  }
}

tôi đã sử dụng 'thực thể không tồn tại' và 10 là loại thực thể và ID thực thể. Nếu bạn có giá trị thực sự cho chúng, bạn nên sử dụng chúng.

Lưu ý rằng FileUsageBase::add(), các DatabaseFileUsageBackend::add() phương thức cha, thay đổi tệp thành vĩnh viễn, trong trường hợp chưa có.

// Đảm bảo rằng tệp được sử dụng là vĩnh viễn.
if (!$file->isPermanent()) {
  $file->setPermanent();
  $file->save();
} 

Khi mức sử dụng tệp giảm xuống và trở thành 0, tệp được thay đổi thành tạm thời từ FileUsageBase::delete().

// Nếu không còn tập tin nào được sử dụng nữa, hãy đánh dấu nó là tạm thời,
// dẫn đến việc xóa thông qua system_cron().
$usage = \Drupal::service('file.usage')->listUsage($file);
nếu (trống ($ sử dụng)) {
  $file->setTemporary();
  $file->save();
}

Tôi muốn tăng mức sử dụng tệp, thay vì trực tiếp biến tệp thành vĩnh viễn, vì việc giảm mức sử dụng tệp không xung đột với các mô-đun khác có thể đặt cùng một tệp là vĩnh viễn.
Ngoài ra, tôi sẽ sử dụng mã sau đây cho hook_file_download().

hàm mymodule_file_download($uri) {
  if (StreamWrapperManager::getScheme($uri) == 'tạm thời') {
    if ($files = \Drupal::entityTypeManager()->getStorage('file')->loadByProperties(['uri' => $uri])){
      nếu ($file = reset($files)) {
        // Quyền truy cập được cấp.
        if (!$file->isPermanent()) {
          $file->setPermanent();
          $file->save();
        }
        $headers = file_get_content_headers($file);
        trả lại tiêu đề $;
      }
    }
  }
}

Trong trường hợp này, để tạo lại tệp tạm thời, tôi sẽ sử dụng đoạn mã sau.

// Lưu trữ tham chiếu thực thể tệp trong $file.
$usage = \Drupal::service('file.usage')->listUsage($file);
if (trống($usage) && !$file->isTemporary()) {
  $file->setTemporary();
  $file->save();
}

Để đạt được những gì bạn muốn, cũng có thể thay đổi bộ điều khiển cho system.temporary tuyến đường, nhưng điều đó có vẻ quá mức.

quantumized avatar
lá cờ ng
Cảm ơn bạn, vâng, đoạn mã file_file_download() đó là thủ phạm. Tôi bối rối về lý do tại sao tôi không thể sử dụng hook_file_download() trong mô-đun có trọng số cao hơn của mình để ghi đè lên điều đó.
quantumized avatar
lá cờ ng
Tôi đã tìm ra giải pháp thay thế bằng cách đặt tệp thành "isPermanent" nhưng tôi không thích điều này. Bạn có biết nếu điều đó sẽ khiến các tệp không bị xóa khỏi hệ thống khi cần không?
apaderno avatar
lá cờ us
`hook_file_download()` chỉ nhận một URL, không nhận các tiêu đề được trả về bởi các triển khai khác; nếu trường hợp này xảy ra, việc triển khai hook có thể ghi đè quyết định của việc triển khai khác. Mã thực tế gọi chúng chỉ cần kiểm tra một trong số chúng được trả về -1 làm tiêu đề; nó không kiểm tra -1 là giá trị được trả về đầu tiên.
apaderno avatar
lá cờ us
@quantumized Các tệp vĩnh viễn sẽ không bị xóa trong quá trình thu thập tệp rác, nhưng một mô-đun có thể xóa chúng. Nếu mô-đun giữ một danh sách tệp mà nó đã thay đổi thành vĩnh viễn, điều đó có thể thực hiện được.
apaderno avatar
lá cờ us
Tôi cũng đã thêm một lưu ý về điều gì sẽ xảy ra khi mức sử dụng tệp tăng lên: Việc triển khai lõi Drupal của dịch vụ *file.usage* sẽ tự động tạo một tệp tạm thời thành vĩnh viễn.

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.