Kebenaran fail dan muat naik dalam Lucee
Selesaikan ralat Permission denied dalam Lucee: kenal pasti pengguna yang menjalankan enjin, bezakan mod 644/755 dengan 640/750, dan baiki kebenaran muat naik.

Kandungan
- Kebenaran fail dan muat naik dalam Lucee
- Siapa yang menjalankan Lucee dan siapa yang memiliki fail
- Mesej ralat Permission denied yang sebenar
- Direktori mesti boleh dilalui, bukan sekadar dibaca
- Beza 644 dan 755 dengan 640 dan 750
- Muat naik masuk sebagai pengguna perkhidmatan, bukan root
- cffile action="upload" dan had saiz
- Simpan muat naik di luar webroot
- Semak kebenaran dengan getFileInfo() dan fileExists()
- Kenapa chmod 777 bukan penyelesaian
- Jadual gejala dan punca
- Soalan Lazim
- Sumber
Kebenaran fail dan muat naik dalam Lucee
Ralat Permission denied dalam Lucee hampir tidak pernah berpunca daripada enjin. Ia datang daripada dua perkara yang enjin tidak kawal: pengguna sistem yang menjalankan Lucee, dan pengguna atau kumpulan yang memiliki fail serta direktori yang cuba diakses. Artikel ini menunjukkan mesej ralat sebenar yang ditangkap dalam rig, semakan mod yang sebenar, dan pembetulan yang berkesan tanpa chmod 777.
Siapa yang menjalankan Lucee dan siapa yang memiliki fail
Peraturan paling asas ialah proses hanya boleh menulis fail jika pengguna yang menjalankannya memiliki kebenaran tulis pada fail atau direktori itu. Lucee bukan pengguna istimewa. Ia berjalan sebagai pengguna yang melancarkan proses Java, biasanya tomcat, www-data, lucee, atau root.
Dalam rig ujian artikel ini, proses Lucee berjalan sebagai root. Fakta itu ditangkap terus daripada enjin dan outputnya ialah root. Ini bermakna apa-apa fail yang ditulis oleh cffile dimiliki oleh root:root. Pada pelayan pengeluaran, Lucee selalunya berjalan sebagai tomcat atau www-data, jadi fail yang ditulisnya dimiliki oleh pengguna itu. Kesilapan paling kerap berlaku apabila seseorang menyalin fail sebagai root, kemudian tertanya-tanya kenapa Lucee yang berjalan sebagai pengguna perkhidmatan tidak boleh menulisnya.
Mesej ralat Permission denied yang sebenar
Kerana rig ini menjalankan Lucee sebagai root, operasi tulis daripada enjin itu sendiri tidak boleh dipaksa gagal dengan Permission denied, sebab root memintas bit kebenaran. Untuk menangkap ralat sebenar, ujian dijalankan sebagai pengguna bukan root bernama ubuntu (uid 1000), iaitu peranan yang sama dengan pengguna perkhidmatan pada pelayan sebenar. Tiga mesej di bawah ditangkap verbatim:
sh: 1: cannot create /opt/kebenaran/ro/baru.txt: Permission denied
touch: cannot touch '/opt/kebenaran/ro/baru.txt': Permission denied
cat: /opt/kebenaran/nox/dalam.txt: Permission denied
Dua baris pertama ialah kegagalan menulis ke direktori mod 0555. Baris ketiga lebih menarik: fail dalam.txt itu boleh dibaca, tetapi direktori induknya mod 0644 tanpa bit x, jadi sistem menafikan akses sebelum sempat membaca fail.
Direktori mesti boleh dilalui, bukan sekadar dibaca
Bit kebenaran bermaksud perkara berbeza pada fail dan pada direktori. Pada fail, r ialah baca dan w ialah ubah. Pada direktori, r membolehkan senarai nama entri, manakala x membolehkan proses masuk untuk mencapai fail di dalamnya.
Dalam rig, direktori /opt/kebenaran/nox dimod 0644. Ia boleh disenaraikan, tetapi tidak boleh dilalui. cat /opt/kebenaran/nox/dalam.txt memulangkan Permission denied walaupun fail itu mod 0644, sementara ls /opt/kebenaran/nox tetap menyenaraikan dalam.txt kerana bit r membenarkan penyenaraian nama sahaja. Jadi apabila Lucee gagal membaca fail yang sepatutnya boleh dibaca, semak bit x pada setiap direktori dalam laluan, bukan hanya mod fail itu.
Beza 644 dan 755 dengan 640 dan 750
644 dan 755 membuka akses baca kepada semua pengguna sistem, manakala 640 dan 750 mengehadkan akses kepada pemilik dan kumpulan. Nombor itu tiga digit: pemilik, kumpulan, lain-lain.
644 bermaksud pemilik boleh baca dan tulis, yang lain hanya baca, sesuai untuk fail statik yang dihidangkan kepada semua orang. 640 bermaksud pemilik baca dan tulis, kumpulan baca, orang lain tiada akses, sesuai untuk fail konfigurasi. Untuk direktori, 755 membolehkan pemilik menulis dan semua lalu, manakala 750 hanya pemilik dan kumpulan lalu. Corak 640 dan 750 hanya berfungsi apabila Lucee berada dalam kumpulan yang sama dengan pemilik fail, jika tidak Lucee dianggap "lain-lain" dan ditolak.
Muat naik masuk sebagai pengguna perkhidmatan, bukan root
Apabila pelawat memuat naik fail, fail itu ditulis oleh proses Lucee, jadi pemiliknya ialah pengguna perkhidmatan. Sebaliknya, fail yang disalin secara manual sebagai root kekal dimiliki root. Dua laluan yang kelihatan sama menghasilkan pemilikan berbeza, dan itulah sebabnya muat naik boleh berjaya sementara fail yang disalin gagal. Ini terbukti dalam rig, di mana fail yang ditulis melalui cffile muncul sebagai milik root:root kerana rig berjalan sebagai root. Panduan penuh menguruskan pemilikan dalam bekas ada dalam artikel Docker dan deploy Lucee.
cffile action="upload" dan had saiz
cffile dengan action="upload" memindahkan fail daripada permintaan multipart ke cakera dan menyimpan hasilnya dalam struktur result. Lucee tidak menyediakan atribut saiz maksimum pada cffile, jadi had saiz disemak selepas muat naik melalui result.fileSize, kemudian fail yang terlalu besar dipadam:
<cffile
action="upload"
destination="/tmp"
fileField="form.fail"
nameConflict="makeunique"
result="up">
<cfif up.fileSize GT 5242880>
<cffile action="delete" file="#up.serverDirectory#/#up.serverFile#">
<cfthrow message="Fail melebihi had 5 MB">
</cfif>
<cfoutput>Muat naik berjaya: #up.serverFile# (#up.fileSize# bait)</cfoutput>
Dalam rig, muat naik fail 25 bait memulangkan fileWasSaved=true, serverFile=ujian-muatnaik.txt, dan fileSize=25, kemudian fileExists() memulangkan true. Operasi cffile untuk baca dan tulis biasa diterangkan dalam artikel cffile baca tulis, manakala semakan jenis fail yang selamat ada dalam panduan muat naik fail yang selamat.
Simpan muat naik di luar webroot
Fail yang dimuat naik tidak sepatutnya disimpan dalam webroot, kerana fail boleh laksana seperti .cfm, .jsp atau .php boleh dipanggil terus melalui URL. Simpan di luar webroot, contohnya /srv/uploads, dan hidangkan semula melalui skrip. Direktori itu mesti dimiliki oleh pengguna perkhidmatan dan dimod paling ketat yang masih berfungsi:
stat -c "%A %a %U:%G %n" /tmp/cuba-tulis.txt
# -rw-r--r-- 644 root:root /tmp/cuba-tulis.txt
chown -R www-data:www-data /srv/uploads
chmod 750 /srv/uploads
chmod 640 /srv/uploads/nota.txt
Baris stat menunjukkan fail yang ditulis oleh Lucee dalam rig ini dimiliki root:root. Pada pelayan sebenar, tukar pemilikan kepada pengguna perkhidmatan Lucee dan guna 750 untuk direktori serta 640 untuk fail. Prinsip menyekat akses ini sama seperti yang diterangkan dalam panduan keselamatan web XSS dan CSRF.
Semak kebenaran dengan getFileInfo() dan fileExists()
Sebelum menulis atau selepas memuat naik, sahkan keadaan fail dengan fileExists() dan getFileInfo(). Lucee tidak menyediakan fungsi bernama isReadable() atau isWritable(), kedua-duanya tiada dalam senarai fungsi enjin ini, jadi gunakan kunci canRead dan canWrite daripada getFileInfo():
<cfscript>
sys = createObject("java", "java.lang.System");
writeOutput("pengguna: " & sys.getProperty("user.name") & "<br>");
info = getFileInfo("/tmp/cuba-tulis.txt");
writeOutput("fileExists: " & fileExists("/tmp/cuba-tulis.txt") & "<br>");
writeOutput("canRead=" & info.canRead & " canWrite=" & info.canWrite);
</cfscript>
Dalam rig yang berjalan sebagai root, canRead dan canWrite memulangkan true untuk hampir semua laluan kerana root memintas bit kebenaran. Nilai ini menggambarkan kebenaran pengguna semasa, jadi pada pelayan yang menjalankan Lucee sebagai pengguna perkhidmatan ia menjadi penunjuk sebenar. Untuk membaca mod POSIX mentah dan pemilik daripada CFML, gunakan Java NIO melalui Files.getPosixFilePermissions() dan Files.getOwner(), yang turut disahkan berfungsi dalam rig.
Kenapa chmod 777 bukan penyelesaian
chmod 777 menjadikan fail boleh dibaca, ditulis dan dilalui oleh sesiapa sahaja, termasuk setiap akaun dan proses pada mesin itu. Ia menghilangkan ralat seketika tetapi meninggalkan fail terbuka, dan ia tidak menyelesaikan punca sebenar.
Punca sebenar hampir selalu salah satu daripada tiga: pemilik fail tidak sepadan dengan pengguna perkhidmatan, kumpulan tidak dikongsi, atau bit laluan pada direktori hilang. Pembetulannya ialah memilih pemilik dan kumpulan yang tepat, kemudian guna mod paling ketat yang masih berfungsi, iaitu 640 dan 750. Jika sistem menggunakan SELinux atau AppArmor, chmod 777 tetap tidak membantu kerana kedua-duanya menafikan akses berdasarkan polisi, bukan bit mod. Rig ini tidak menjalankan SELinux mahupun AppArmor, jadi lapisan itu tidak dapat diuji di sini dan mesti disemak pada pelayan sebenar dengan ls -Z atau aa-status.
Jadual gejala dan punca
| Gejala Permission denied | Punca | Pembetulan |
|---|---|---|
Fail wujud tetapi Lucee tidak boleh tulis, fail dimiliki root | Pemilik fail salah, fail disalin sebagai root | chown kepada pengguna perkhidmatan Lucee |
| Pengguna betul tetapi akses tetap ditolak | Kumpulan tidak sepadan dengan mod 640 atau 750 | Tambah Lucee ke kumpulan, guna mod 640/750 |
| Fail boleh dibaca tetapi tidak boleh dicapai | Direktori dalam laluan tiada bit x | chmod 750 pada direktori laluan |
Mod 777 tetapi masih ditolak | SELinux atau AppArmor menafikan akses | Semak ls -Z atau aa-status, laraskan polisi |
| Muat naik gagal selepas deploy | Destinasi dalam webroot dimiliki root | Simpan di luar webroot, chown dan chmod 750 |
Soalan Lazim
Kenapa fail yang saya salin sebagai root tidak boleh ditulis oleh Lucee?
Kerana Lucee berjalan sebagai pengguna perkhidmatan seperti tomcat atau www-data, manakala fail yang anda salin sebagai root dimiliki oleh root. Apabila Lucee cuba menulis, sistem menganggapnya "lain-lain" dan menafikan akses. Tukar pemilikan dengan chown kepada pengguna atau kumpulan Lucee.
Apakah perbezaan 644/755 dengan 640/750?
644 dan 755 membenarkan semua pengguna sistem membaca, manakala 640 dan 750 mengehadkan akses kepada pemilik dan kumpulan sahaja. Gunakan 640 untuk fail dan 750 untuk direktori apabila fail itu hanya perlu diakses oleh Lucee dan kumpulannya.
Kenapa direktori perlu bit x dan bukan sekadar dibaca?
Bit r pada direktori hanya membenarkan senarai nama entri, manakala bit x membenarkan proses masuk ke dalam direktori untuk mencapai fail di dalamnya. Tanpa x, sistem menafikan akses kepada fail walaupun fail itu sendiri boleh dibaca.
Bagaimana saya semak kebenaran fail daripada kod CFML?
Gunakan fileExists() untuk kewujudan dan getFileInfo() untuk sifat canRead dan canWrite. Lucee tidak menyediakan fungsi isReadable() atau isWritable(), jadi jangan gunakan nama itu. Untuk mod POSIX dan pemilik, gunakan Java NIO.
Adakah chmod 777 menyelesaikan masalah Permission denied?
Tidak secara kekal. Ia membuka fail kepada setiap pengguna dan proses pada mesin, dan ia tidak menyelesaikan punca sebenar iaitu pemilik, kumpulan atau mod yang salah. Gunakan pemilikan yang tepat dengan mod paling ketat yang masih berfungsi.