PHP: Check if a file is loaded directly instead of

2019-01-05 02:08发布

Is there a way to prevent a user viewing an file but still use it as included to another file in PHP?

标签: php file include
15条回答
We Are One
2楼-- · 2019-01-05 02:10

There are many good answers in this thread - here's one that hasn't been mentioned yet.

You can name your included PHP files with an i in the extension, e.g. someincludedfile.phpi and then configure Apache so that it doesn't serve phpi files. Voila.

Cons:

  • (!) highly dependent on the Apache configuration (so you're vulnerable if someone neglects that line) -- and in such a event, the browser might get to see the whole PHP script in plaintext since it won't get passed off to PHP (really bad!)
  • it can be annoying to rename your included files

Pros:

  • makes it clear which files are to be included and which aren't in your code
  • you don't have to move your file hierarchy around

Personally, I would rather just move files into a directory outside the document root, but if you have a large legacy application, this could be quicker to change.

Link: http://www.ducea.com/2006/07/21/apache-tips-tricks-deny-access-to-certain-file-types/

查看更多
老娘就宠你
3楼-- · 2019-01-05 02:13

If you want to stop it from ever being displayed when not included here's a more automated way.

if (basename(__FILE__) == basename($_SERVER['PHP_SELF'])) header("HTTP/1.0 404 Not Found");

This way it'll still work if you end up changing the file name or something.

查看更多
冷血范
4楼-- · 2019-01-05 02:13

Just to expand on the solutions with $_SERVER variables - below is a small .php file, and in the comments is a copy of a bash test I did on Ubuntu; the point being, that these variables can change quite a bit depending on the type of access, and whether symlinks are used (note also, in the code below I have to escape the '?\>' in the echo statement, else the syntax color breaks; remove the backslash if trying the code):

<?php

function report($label, $value) {
  printf ("%23s: %s\n", $label, $value);
}

report("DOCUMENT_ROOT.PHP_SELF",  $_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF'] );
report("SCRIPT_FILENAME",         $_SERVER['SCRIPT_FILENAME'] );
report("__FILE__",                __FILE__ );
report("PHP_SAPI",                PHP_SAPI );

/*
# the test (bash):

home~$ mkdir /tmp/ptest
home~$ cd /tmp/ptest/
ptest$ ln -s /real/path/to/varcheck.php .
ptest$ echo '<? require_once "varcheck.php"; ?\>' > varcheckincl.php


# ... and in a separate terminal, run
# php (>5.4) cli server at same (/tmp/ptest) location:

ptest$ php-5.4.10 -S localhost:8000

# back to first terminal, the test - and output:

ptest$ php varcheck.php
 DOCUMENT_ROOT.PHP_SELF: varcheck.php
        SCRIPT_FILENAME: varcheck.php
               __FILE__: /real/path/to/varcheck.php
               PHP_SAPI: cli

ptest$ php -r 'require_once "varcheck.php";'
 DOCUMENT_ROOT.PHP_SELF: -
        SCRIPT_FILENAME:
               __FILE__: /real/path/to/varcheck.php
               PHP_SAPI: cli

ptest$ php varcheckincl.php
 DOCUMENT_ROOT.PHP_SELF: varcheckincl.php
        SCRIPT_FILENAME: varcheckincl.php
               __FILE__: /real/path/to/varcheck.php
               PHP_SAPI: cli

ptest$ wget http://localhost:8000/varcheck.php -q -O -
 DOCUMENT_ROOT.PHP_SELF: /tmp/ptest/varcheck.php
        SCRIPT_FILENAME: /tmp/ptest/varcheck.php
               __FILE__: /real/path/to/varcheck.php
               PHP_SAPI: cli-server

ptest$ wget http://localhost:8000/varcheckincl.php -q -O -
 DOCUMENT_ROOT.PHP_SELF: /tmp/ptest/varcheckincl.php
        SCRIPT_FILENAME: /tmp/ptest/varcheckincl.php
               __FILE__: /real/path/to/varcheck.php
               PHP_SAPI: cli-server
*/
?>
查看更多
神经病院院长
5楼-- · 2019-01-05 02:16
if (!defined('FLAG_FROM_A_PARENT'))
// Works in all scenarios but I personally dislike this

if (__FILE__ == get_included_files()[0])
// Doesn't work with PHP prepend unless calling [1] instead.

if (__FILE__ == $_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_FILENAME'])
// May break on Windows due to mixed DIRECTORY_SEPARATOR

if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']))
// Doesn't work with files with the same basename but different paths

if (realpath(__FILE__) == realpath($_SERVER['DOCUMENT_ROOT'].$_SERVER['SCRIPT_NAME']))
// Seems to do the trick
查看更多
Emotional °昔
6楼-- · 2019-01-05 02:17

I'd go for Chacha102's solution.

Additionally, as your question title says «how to check», you can also do this without having to define a variable by using

// secret.php is the name of this file.
if($_SERVER["SCRIPT_FILENAME"]=='secret.php') die();
查看更多
该账号已被封号
7楼-- · 2019-01-05 02:17

Do not use any global code in your files, only functions and methods. Then there will be no need to care about include vs. direct use.

查看更多
登录 后发表回答