Score:1

เป็นไปได้ไหมที่จะอนุญาตให้ผู้ใช้ที่ไม่ระบุชื่อดูไฟล์ที่จัดการชั่วคราวผ่าน hook_file_download()

ธง ng

ฉันกำลังสร้างระบบแสดงตัวอย่างภาพสดสำหรับผลิตภัณฑ์ที่ปรับแต่งได้ซึ่งจำเป็นต้องส่งไฟล์ชั่วคราวของผู้ใช้ไปยังเซิร์ฟเวอร์ระยะไกล

ฉันมีระบบที่ใช้โทเค็นเพื่อป้องกันไฟล์ แต่ดูเหมือนว่าปัญหาคือไฟล์เป็นแบบชั่วคราว ฉันได้สร้าง hook_file_download() เพื่อส่งคืนส่วนหัวตามที่จำเป็นเพื่ออนุญาตการเข้าถึงเมื่อได้รับการอนุมัติ แต่การเข้าถึงไฟล์ยังคงถูกปฏิเสธที่ใดที่หนึ่ง

ดูเหมือนจะไม่เป็นปัญหาเกี่ยวกับน้ำหนักของโมดูล เนื่องจากฉันได้ทำให้โมดูลที่กำหนดเองของฉันมีน้ำหนักต่ำสุดและตรวจสอบผ่านรหัสดีบั๊กที่มันทำงานหลังจากไฟล์หลัก file_file_download()

แก้ไข: การแก้ไขปัญหาเพิ่มเติมแสดงให้เห็นว่าอาร์เรย์ส่วนหัวได้รับค่าคีย์ที่ตั้งค่าเป็น "-1" ที่ใดที่หนึ่งหลังจาก hook_file_download() และคอร์ "FileDownloadController" ซึ่งเป็นที่ที่ไฟล์ถูกปฏิเสธ ความคิดใด ๆ ที่ค่าส่วนหัว [0] = -1 นี้ได้รับการตั้งค่าและจะแทนที่ได้อย่างไร

ถ้าฉันแยกมันออกเป็นพื้นฐานสำหรับการทดสอบตามที่แสดงด้านล่าง ส่วนหัว 'อนุญาต' จะถูกส่งกลับ แต่ไฟล์ยังคงถูกบล็อกเมื่อดูจากเบราว์เซอร์ที่ไม่ระบุตัวตน:

ฟังก์ชัน MYMODULE_file_download($uri) {

  // ตรวจสอบเพื่อดูว่านี่คือการดาวน์โหลดการกำหนดค่าหรือไม่
  $scheme = StreamWrapperManager::getScheme($uri);

  ถ้า ($scheme == 'ชั่วคราว'){
    ถ้า ($files = \Drupal::entityTypeManager()->getStorage('file')->loadByProperties(['uri' => $uri])){

      $file = reset($files) ?: โมฆะ;
      
      // อนุญาตการเข้าถึง
      $headers = file_get_content_headers($ไฟล์);
      กลับหัว $;
    }
  }
}
Score:1
ธง us

ไฟล์ชั่วคราวถูกจัดการโดย file_file_download()การดำเนินการของ hook_file_download() ทำได้จากโมดูลไฟล์ รหัสที่ใช้คือรหัสต่อไปนี้

  // ค้นหาว่ายังมีการใช้ไฟล์ชั่วคราวในระบบหรือไม่
  ถ้า ($file->isTemporary()) {
    $usage = \Drupal::service('file.usage')->listUsage($file);
    ถ้า (ว่าง($usage) && $file->getOwnerId() != \Drupal::currentUser()
      ->รหัส()) {
      // ปฏิเสธการเข้าถึงไฟล์ชั่วคราวโดยไม่มีการใช้งานที่ไม่ใช่ของ
      // ผู้ใช้คนเดียวกัน ซึ่งจะป้องกันปัญหาด้านความปลอดภัยที่ไฟล์ส่วนตัวนั้น
      // ได้รับการคุ้มครองโดยการอนุญาตของฟิลด์จะพร้อมใช้งานหลังจากการใช้งาน
      // ถูกลบออกและก่อนที่จะถูกลบออกจากระบบไฟล์จริง
      // โมดูลที่ขึ้นอยู่กับลักษณะการทำงานนี้ควรทำให้ไฟล์เป็นแบบถาวร
      // แทน.
      กลับ -1;
    }
  }

การอ่านความคิดเห็นที่ทำขึ้นเพื่อหลีกเลี่ยงไฟล์ส่วนตัว ซึ่งได้รับการป้องกันโดยสิทธิ์ของฟิลด์ จะมองเห็นได้หลังจากเปลี่ยนสิทธิ์ของฟิลด์ แต่ก่อนที่ไฟล์จะถูกลบ

ดูรหัสที่เรียกใช้ hook นั้นใน FileDownloadController::download() ตัวอย่างเช่น ฉันไม่เห็นวิธีหลีกเลี่ยง เนื่องจากรหัสไม่ได้ใช้ hook_file_download_alter().

วิธีแก้ไขปัญหาคือตั้งค่าไฟล์นั้นว่ากำลังใช้งาน เนื่องจากรหัสจะตรวจสอบไฟล์ว่าไม่ได้ใช้ ก่อนที่จะบล็อกการเข้าถึง

ฟังก์ชัน mymodule_file_download($uri) {
  ถ้า (StreamWrapperManager::getScheme($uri) == 'ชั่วคราว') {
    ถ้า ($files = \Drupal::entityTypeManager()->getStorage('file')->loadByProperties(['uri' => $uri])){
      ถ้า ($file = รีเซ็ต ($files)) {
        // อนุญาตการเข้าถึง
        \Drupal::service('file.usage')->add($file, 'mymodule', 'unexisting_entity', 10);
        $headers = file_get_content_headers($ไฟล์);
        กลับหัว $;
      }
    }
  }
}

ฉันใช้ 'unexisting_entity' และ 10 เป็นประเภทเอนทิตีและรหัสเอนทิตี หากคุณมีค่าที่แท้จริงสำหรับพวกเขา คุณควรใช้สิ่งเหล่านั้น

โปรดทราบว่า FileUsageBase::add(), DatabaseFileUsageBackend::add() วิธีพาเรนต์ ให้เปลี่ยนไฟล์เป็นแบบถาวร ในกรณีที่ยังไม่ได้ทำ

// ตรวจสอบให้แน่ใจว่าไฟล์ที่ใช้เป็นแบบถาวร
ถ้า (!$file->isPermanent()) {
  $file->setPermanent();
  $file->save();
} 

เมื่อการใช้งานไฟล์ลดลงและกลายเป็น 0 ไฟล์จะเปลี่ยนเป็นชั่วคราวจาก FileUsageBase::ลบ().

// หากไม่มีการใช้งานไฟล์นี้เหลืออยู่ ให้ทำเครื่องหมายเป็นไฟล์ชั่วคราว
// ซึ่งส่งผลให้เกิดการลบผ่าน system_cron()
$usage = \Drupal::service('file.usage')->listUsage($file);
ถ้า (ว่าง ($ การใช้งาน)) {
  $file->setTemporary();
  $file->save();
}

ฉันอยากจะเพิ่มการใช้ไฟล์ แทนที่จะสร้างไฟล์ถาวรโดยตรง เนื่องจากการลดการใช้ไฟล์จะไม่ขัดแย้งกับโมดูลอื่นๆ ที่สามารถตั้งค่าไฟล์เดียวกันเป็นแบบถาวรได้
หรือฉันจะใช้รหัสต่อไปนี้สำหรับ hook_file_download().

ฟังก์ชัน mymodule_file_download($uri) {
  ถ้า (StreamWrapperManager::getScheme($uri) == 'ชั่วคราว') {
    ถ้า ($files = \Drupal::entityTypeManager()->getStorage('file')->loadByProperties(['uri' => $uri])){
      ถ้า ($file = รีเซ็ต ($files)) {
        // อนุญาตการเข้าถึง
        ถ้า (!$file->isPermanent()) {
          $file->setPermanent();
          $file->save();
        }
        $headers = file_get_content_headers($ไฟล์);
        กลับหัว $;
      }
    }
  }
}

ในกรณีนี้ หากต้องการสร้างไฟล์ชั่วคราวอีกครั้ง ฉันจะใช้รหัสต่อไปนี้

// เก็บการอ้างอิงเอนทิตีของไฟล์ไว้ใน $file
$usage = \Drupal::service('file.usage')->listUsage($file);
ถ้า (ว่าง ($ การใช้งาน) && !$file->isTemporary()) {
  $file->setTemporary();
  $file->save();
}

เพื่อให้บรรลุตามที่คุณต้องการ คุณยังสามารถเปลี่ยนคอนโทรลเลอร์สำหรับ ระบบชั่วคราว เส้นทาง แต่นั่นดูมากเกินไป

quantumized avatar
ng flag
ขอบคุณใช่ file_file_download() snippet นั้นเป็นตัวการ ฉันสับสนว่าทำไมฉันถึงไม่สามารถใช้ hook_file_download() ในโมดูลที่มีน้ำหนักสูงกว่าเพื่อแทนที่สิ่งนั้นได้
quantumized avatar
ng flag
ฉันพบวิธีแก้ปัญหาโดยตั้งค่าไฟล์เป็น "isPermanent" แต่ฉันไม่ชอบสิ่งนี้ คุณรู้หรือไม่ว่าจะทำให้ไฟล์ไม่ถูกลบออกจากระบบเมื่อจำเป็น?
apaderno avatar
us flag
`hook_file_download()` รับเฉพาะ URL ไม่ใช่ส่วนหัวที่ส่งคืนโดยการใช้งานอื่น หากเป็นกรณีนี้ การใช้ hook อาจมีผลเหนือการตัดสินใจของการใช้งานอื่น รหัสจริงที่เรียกพวกเขาเพียงแค่ตรวจสอบหนึ่งในนั้นกลับ -1 เป็นส่วนหัว; มันไม่ได้ตรวจสอบ -1 เป็นค่าแรกที่ส่งคืน
apaderno avatar
us flag
ไฟล์ถาวร @quantumized จะไม่ถูกลบในระหว่างกระบวนการรวบรวมไฟล์ขยะ แต่โมดูลสามารถลบออกได้ หากโมดูลเก็บรายการไฟล์ที่เปลี่ยนเป็นถาวร ก็อาจเป็นไปได้
apaderno avatar
us flag
ฉันยังได้เพิ่มหมายเหตุเกี่ยวกับสิ่งที่จะเกิดขึ้นเมื่อการใช้งานไฟล์เพิ่มขึ้น: การใช้งานหลักของ Drupal ของบริการ *file.usage* จะทำให้ไฟล์ชั่วคราวเป็นแบบถาวรโดยอัตโนมัติ

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา