How to detect if a file is being included or directly ran

前端 未结 6 929
春和景丽
春和景丽 2021-01-20 00:09

I have a php file that I include in my php script, but I don\'t want people to be able to directly run the file(without being included). How can I prevent that from happenin

相关标签:
6条回答
  • 2021-01-20 00:37

    I've seen this pattern in some applications:

    1. Main, directly run file runs define('SOMETHING', 'SOMEVALUE');
    2. Included file starts with if(!defined('SOMETHING')) return;
    0 讨论(0)
  • 2021-01-20 00:47

    Make the included scripts not accessible via HTTP at all. E.g. by protecting the subfolder or moving them above the document root.

    If you cannot do that, define() something like IS_INCLUDED in your main script and exit; if this constant is not defined() in your included script.

    0 讨论(0)
  • 2021-01-20 00:47

    2 solutions for a good protection:

    1. Apache

    with htaccess:

    RedirectMatch 404 "\.(sql|sh|java|class|inc\.php)$"
    

    Or in /etc/apache2/sites-enabled:

    <VirtualHost *:80>
    #...
    RedirectMatch 404 "\.(sql|sh|java|class|inc\.php)$"
    #...
    </VirtualHost>
    

    Then name your file like this: myInternalFileIncludeOnly.inc.php

    1. PHP

    With this sample code, PHP is able to detect include:

    if( get_included_files()[0] == __FILE__ ){
        echo '2.php direct access';
    }else{
        echo '2.php was included';
    }
    

    EDIT: See Tim answer, so if you have a prepend include (cf php.ini) use this:

    if(
        (!ini_get('auto_prepend_file') && get_included_files()[0] === __FILE__)
        ||
        ini_get('auto_prepend_file') && (($__FILE__=str_replace('\\','/',__FILE__)) === str_replace('\\','/',$_SERVER['DOCUMENT_ROOT'].$_SERVER['SCRIPT_FILENAME']) || $__FILE__ === str_replace('\\','/',$_SERVER['SCRIPT_FILENAME']) )
    )
        echo '2.php direct access',"\n";
    
    0 讨论(0)
  • 2021-01-20 00:51

    Checking if the script is the parent of the PHP process might not be the best idea for preventing users of requesting an include file directly. But it can be handy in many other cases i.e. AJAX modules etc. I'm not gonna start a new topic by 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 not work on Windows due to mixed DIRECTORY_SEPARATOR (machine specific)
    
    if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME']))
    // Doesn't work with files with the same basename but different paths
    
    if (defined('FLAG_FROM_A_PARENT'))
    // Works in all scenarios but I personally dislike this
    
    if (realpath(__FILE__) == realpath($_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_FILENAME']))
    // Should work flawlessly
    

    Keep in mind some machines that use virtual paths may return different paths in different php components. realpath() is your friend for this.

    0 讨论(0)
  • 2021-01-20 00:56

    Included PHP files should contain class/function/variable definitions, not inline logic/output.

    Running them directly is then, essentially, a no-op.

    0 讨论(0)
  • 2021-01-20 01:01

    I use a sentinel constant, defined in the "including" script, and the "included" script looks for it.

    Example:

    /* main.php */
    define('SENTINEL', 1);
    include "included.inc.php"
    
    /* included.inc.php */
    if (!defined('SENTINEL')) die("Wanted to be smart?? Nice try.");
    
    0 讨论(0)
提交回复
热议问题