Pergunta

Eu tenho um arquivo php que eu vou estar usando como exclusivamente como um include. Portanto, eu gostaria de lançar um erro em vez de executá-lo quando ele é acessado diretamente, digitando o URL em vez de ser incluído.

Basicamente eu preciso fazer uma verificação da seguinte forma no arquivo php:

if ( $REQUEST_URL == $URL_OF_CURRENT_PAGE ) die ("Direct access not premitted");

Existe uma maneira fácil de fazer isso?

Foi útil?

Solução

A maneira mais fácil para o "app PHP rodando em um servidor Apache que você pode ou não pode controlar totalmente" genérico situação é colocar o seu inclui em um diretório e negar o acesso a esse diretório em seu arquivo .htaccess. Para salvar as pessoas o trabalho de pesquisando, se você estiver usando Apache, colocar isso em um arquivo chamado ".htaccess" no diretório que você não quer ser acessível:

Deny from all

Se você realmente tem o controle completo do servidor (mais comum nos dias de hoje, mesmo para pequenos aplicativos que quando escrevi pela primeira vez esta resposta), a melhor abordagem é manter os arquivos que você quer fora proteção do diretório que seu servidor web está servindo a partir. Portanto, se seu aplicativo está em /srv/YourApp/, definir o servidor para servir arquivos de /srv/YourApp/app/ e colocar o inclui no /srv/YourApp/includes, então não há literalmente não é qualquer URL que possa acessá-los.

Outras dicas

Adicione esta para a página que você quer apenas ser incluídos

<?php
if(!defined('MyConst')) {
   die('Direct access not permitted');
}
?>

, em seguida, nas páginas que incluí-lo adicionar

<?php
define('MyConst', TRUE);
?>

Eu tenho um arquivo que eu preciso agir de forma diferente quando ele está incluído vs quando ele é acessado diretamente (principalmente um print() vs return()) Aqui está um código modificado:

if(count(get_included_files()) ==1) exit("Direct access not permitted.");

O arquivo que está sendo acessado é sempre um arquivo incluído, daí o == 1.

A melhor maneira de impedir o acesso direto aos arquivos é colocá-los fora da raiz do documento web-servidor (normalmente, um nível acima). Você ainda pode incluí-los, mas não há nenhuma possibilidade de alguém acessá-los através de uma solicitação HTTP.

Eu costumo percorrer todo o caminho, e colocar todo o meu PHP arquivos fora da raiz do documento, além do inicialização arquivo -. um index.php solitário na raiz do documento que começa roteamento todo o site / aplicativo

Uma alternativa (ou complemento) para solução de Chuck seria negar o acesso a arquivos correspondentes a um padrão específico, colocando algo como isto em seu arquivo .htaccess

<FilesMatch "\.(inc)$">
    Order deny,allow
    Deny from all
</FilesMatch>

1: Verificar a contagem de arquivos incluídos

if( count(get_included_files()) == ((version_compare(PHP_VERSION, '5.0.0', '>='))?1:0) )
{
    exit('Restricted Access');
}

Logic: saídas PHP se o mínimo incluem contagem não for cumprida. Note que antes de PHP5, a página de base não é considerado um include.


2: Definir e verificar uma constante global

// In the base page (directly accessed):
define('_DEFVAR', 1);

// In the include files (where direct access isn't permitted):
defined('_DEFVAR') or exit('Restricted Access');

Logic:. Se a constante não é definido, em seguida, a execução não começou a partir da página de base, e PHP iria parar a execução


3: autorização remoto endereço

// Call the include from the base page(directly accessed):
$includeData = file_get_contents("http://127.0.0.1/component.php?auth=token");

// In the include files (where direct access isn't permitted):
$src = $_SERVER['REMOTE_ADDR']; // Get the source address
$auth = authoriseIP($src); // Authorisation algorithm
if( !$auth ) exit('Restricted Access');

O problema com este método é isolado execução, a menos que uma sessão de token fornecido com o pedido interno. Verifique através do endereço de auto-retorno em caso de uma configuração de servidor único, ou um endereço de lista branca para um multi-servidor ou infraestrutura de servidores com balanceamento de carga.


4: autorização token

Semelhante ao método anterior, pode-se usar GET ou POST para passar uma autorização token para o arquivo de inclusão:

if($key!="serv97602"){header("Location: ".$dart);exit();}

Um método muito confuso, mas também talvez o mais seguro e versátil, ao mesmo tempo, quando usado da maneira correta.


5: Webserver específica de configuração

A maioria dos servidores permitem que você atribuir permissões para arquivos individuais ou diretórios. Você poderia colocar todo o seu inclui nessas listas restritas, e ter o servidor configurado para negá-los.

Por exemplo, em APACHE, a configuração é armazenada no arquivo .htaccess. Tutorial aqui .

Nota no entanto que as configurações específicas do servidor não são recomendados por mim, porque eles são ruins para a portabilidade entre diferentes servidores web. Em tais casos em que o negam-algoritmo é complexo ou a lista de diretórios negado é bastante grande, ele só pode fazer sessões de reconfiguração bastante horrível. No final, é melhor para lidar com isso no código.


6: Colocação inclui em um FORA diretório seguro a raiz do site

Pelo menos preferido por causa das limitações de acesso em ambientes de servidor, mas um método bastante poderoso, se você tem acesso ao sistema de arquivos.

//Your secure dir path based on server file-system
$secure_dir=dirname($_SERVER['DOCUMENT_ROOT']).DIRECTORY_SEPARATOR."secure".DIRECTORY_SEPARATOR;
include($secure_dir."securepage.php");

Logic:

  • O usuário não pode pedir qualquer arquivo fora da pasta htdocs como as ligações seria fora do âmbito do sistema o endereço do website.
  • O servidor php acessa o sistema de arquivos de forma nativa, e, portanto, pode acessar arquivos em um computador da mesma forma como um programa normal com privilégios necessários pode.
  • Ao colocar os arquivos de inclusão neste diretório, você pode garantir que o servidor php consegue acessá-los, enquanto hotlinking é negado para o usuário.
  • Mesmo configuração de acesso sistema de arquivos do servidor web não foi feito corretamente, este método impediria esses arquivos se torne pública acidentalmente.

Por favor, desculpem meus convenções de codificação heterodoxas. Qualquer feedback é apreciado.

Na verdade, o meu conselho é para fazer todas essas melhores práticas.

  • Coloque os documentos fora do webroot ou em um diretório negado o acesso pelo servidor web E
  • Use a definir em seus documentos visíveis que os documentos escondidos verificar:
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

Desta forma, se os arquivos tornam-se extraviado de alguma forma (uma operação ftp errante) eles ainda estão protegidos.

Eu tive esse problema uma vez, resolvido com:

if (strpos($_SERVER['REQUEST_URI'], basename(__FILE__)) !== false) ...

mas a solução ideal é colocar a parte externa da raiz do documento web-servidor de arquivos, como mencionado em outro anwser.

É melhor aplicação de compilação com um ponto de entrada, ou seja, todos os arquivos devem ser alcançado a partir de index.php

Coloque este em index.php

define(A,true);

Esta verificação deve ser executado em cada arquivo vinculado (via exigem ou incluir)

defined('A') or die(header('HTTP/1.0 403 Forbidden'));

A maneira mais fácil é definir algumas variáveis ??no arquivo que as chamadas incluem, como

$including = true;

Em seguida, no arquivo que está sendo incluído, verificação para a variável

if (!$including) exit("direct access not permitted");

O Joomla! não está a definir uma constante em um arquivo de raiz e verificar se o mesmo é definido nos arquivos incluídos.

defined('_JEXEC') or die('Restricted access');

ou então

pode-se manter todos os arquivos fora do alcance de uma solicitação HTTP, colocando-os fora do diretório webroot como a maioria dos frameworks como CodeIgniter recomendar.

ou até mesmo colocando um arquivo .htaccess dentro da pasta incluem e escrever regras, você pode impedir o acesso direto.

debug_backtrace() || die ("Direct access not permitted");

Eu queria restringir o acesso ao PHP arquivo diretamente, mas também ser capaz de chamá-lo via jQuery $.ajax (XMLHttpRequest). Aqui está o que funcionou para mim.

if (empty($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] != "XMLHttpRequest") {
    if (realpath($_SERVER["SCRIPT_FILENAME"]) == __FILE__) { // direct access denied
        header("Location: /403");
        exit;
    }
}

Além da maneira .htaccess, tenho visto um padrão útil em vários quadros, por exemplo, em Ruby on Rails. Eles têm um pub / diretório separado no diretório raiz do aplicativo e os diretórios de bibliotecas estão vivendo em diretórios no mesmo nível como pub /. Algo assim (não é o ideal, mas você começa a idéia):

app/
 |
 +--pub/
 |
 +--lib/
 |
 +--conf/
 |
 +--models/
 |
 +--views/
 |
 +--controllers/

Você configurar o servidor web para usar pub / como raiz do documento. Isto oferece uma melhor proteção para seus scripts: enquanto eles podem chegar a partir da raiz do documento para carregar componentes necessários é impossível acessar os componentes da internet. Outro benefício além da segurança é que tudo está em um só lugar.

Esta configuração é melhor do que apenas a criação de cheques em cada arquivo incluído porque "o acesso não permitido" mensagem é uma pista para os atacantes, e é melhor do que a configuração .htaccess porque não é branca-lista com base: se você estragar as extensões de arquivo que não será visível no lib /, conf / etc diretórios.

Se mais precisamente, você deve usar esta condição:

if (array_search(__FILE__, get_included_files()) === 0) {
    echo 'direct access';
}
else {
    echo 'included';
}

get_included_files () retorna matriz indexada contendo nomes de todos arquivos incluídos (se o arquivo é beign executado em seguida, ele foi incluído e seu nome é na matriz). Então, quando o arquivo é acessado diretamente, seu nome é o primeiro na matriz, todos os outros arquivos na matriz foram incluídos.

<?php
if (eregi("YOUR_INCLUDED_PHP_FILE_NAME", $_SERVER['PHP_SELF'])) { 
 die("<h4>You don't have right permission to access this file directly.</h4>");
}
?>

coloque o código acima na parte superior do seu arquivo php incluído.

ex:

<?php
if (eregi("some_functions.php", $_SERVER['PHP_SELF'])) {
    die("<h4>You don't have right permission to access this file directly.</h4>");
}

    // do something
?>

O código a seguir é usado no Flatnux CMS ( http://flatnux.altervista.org ):

if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
    header("Location: ../../index.php");
    die("...");
}

Eu encontrei este php-only e invariável solução que funciona tanto com http e cli:

Definir uma função:

function forbidDirectAccess($file) {
    $self = getcwd()."/".trim($_SERVER["PHP_SELF"], "/");
    (substr_compare($file, $self, -strlen($self)) != 0) or die('Restricted access');
}

Chamada a função no arquivo que você deseja impedir o acesso direto a:

forbidDirectAccess(__FILE__);

A maioria das soluções dadas acima a esta pergunta não funcionam no modo CLI.

if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) { die('Access denied'); };

A minha resposta é um pouco diferente na abordagem, mas inclui muitas das respostas fornecidas aqui. Eu recomendaria uma abordagem múltipla:

  1. .htaccess e Apache restrições para certificar
  2. defined('_SOMECONSTANT') or die('Hackers! Be gone!');

NO ENTANTO a abordagem defined or die tem uma série de falhas. Em primeiro lugar, é uma verdadeira dor nas hipóteses de testar e depurar com. Em segundo lugar, trata-se terrivelmente, tediosamente chato refatoração se você mudar de idéia. "Localizar e substituir!" você diz. Sim, mas como você está certo de que está escrito exatamente o mesmo em todos os lugares, hmmm? Agora multiplique isso com milhares de arquivos ... o.o

E depois há .htaccess. O que acontece se o seu código é distribuído em locais onde o administrador não é tão escrupulosa? Se você contar apenas com .htaccess para proteger seus arquivos você também vai precisar de um) uma cópia de segurança, b) uma caixa de lenços para enxugar suas lágrimas, c) um extintor de incêndio para apagar as chamas em todo o hatemail de pessoas usando seu código.

Então eu sei que a pergunta pede o "mais fácil", mas acho que isso exige é mais "defensiva codificação".

O que eu sugiro é:

  1. Antes de qualquer um dos seus scripts de require('ifyoulieyougonnadie.php'); ( não include() e como um substituto para defined or die)
  2. Em ifyoulieyougonnadie.php, fazer algumas coisas lógica - cheque de diferentes constantes, roteiro chamar, localhost testes e tal -. E, em seguida, implementar o seu die(), throw new Exception, 403, etc

    Estou criando minha própria estrutura com dois pontos de entrada possíveis - a principal index.php (framework Joomla) e ajaxrouter.php (meu quadro) - assim, dependendo do ponto de entrada, eu buscar por coisas diferentes. Se o pedido para ifyoulieyougonnadie.php não vem de um desses dois arquivos, eu sei travessuras estão sendo realizadas!

    Mas o que se eu adicionar um novo ponto de entrada? Não se preocupe. Eu só mudar ifyoulieyougonnadie.php e estou classificadas, além de não 'localizar e substituir'. Hooray!

    E se eu decidiu mudar alguns dos meus scripts para fazer um quadro diferente que não têm a mesma constantes defined()? ... Hooray! ^ _ ^

Eu encontrei essa estratégia torna o desenvolvimento muito mais divertido e muito menos:

/**
 * Hmmm... why is my netbeans debugger only showing a blank white page 
 * for this script (that is being tested outside the framework)?
 * Later... I just don't understand why my code is not working...
 * Much later... There are no error messages or anything! 
 * Why is it not working!?!
 * I HATE PHP!!!
 * 
 * Scroll back to the top of my 100s of lines of code...
 * U_U
 *
 * Sorry PHP. I didn't mean what I said. I was just upset.
 */

 // defined('_JEXEC') or die();

 class perfectlyWorkingCode {}

 perfectlyWorkingCode::nowDoingStuffBecauseIRememberedToCommentOutTheDie();

fazer algo como:

<?php
if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') {
    header('HTTP/1.0 403 Forbidden');
    exit('Forbidden');
}
?>

Você pode usar o seguinte método abaixo embora, ele tem uma falha, porque ele pode ser falsificado, exceto se você pode adicionar uma outra linha de código para garantir que o pedido vem apenas de seu servidor ou usando Javascript. Você pode colocar esse código na seção corpo do seu código HTML, de modo que os shows de erro lá.

<?
if(!isset($_SERVER['HTTP_REQUEST'])) { include ('error_file.php'); }
else { ?>

Coloque seu outro código HTML aqui

<? } ?>

Fim-lo assim, então a saída do erro irá mostrar sempre na secção do corpo, se é assim que você quer que ele seja.

Eu sugiro que não use de $_SERVER por razões de segurança.
Você pode usar uma variável como $root=true; no primeiro arquivo que incluiu outra.
e uso isset($root) no início do segundo arquivo que ser incluídos.

O que você também pode fazer é proteger com senha o diretório e manter todos os seus scripts PHP lá, é claro, exceto o arquivo index.php, como no momento de incluir não será exigida senha, pois ela será necessária apenas para http Acesso. o que ele vai fazer é também fornecer-lhe a opção de acessar seus scripts, caso você queira-o como você vai ter uma senha para acessar o diretório. você precisará arquivo .htaccess configuração para o diretório e um arquivo .htpasswd para autenticar o usuário.

Bem, você também pode usar qualquer uma das soluções fornecidas acima no caso de você sentir que você não precisa de acesso a esses arquivos normalmente porque você sempre pode acessá-los através cPanel etc.

Espero que isso ajude

A maneira mais fácil é para guardar o seu inclui fora do diretório web. Dessa forma, o servidor tem acesso a eles, mas nenhuma máquina fora. A única desvantagem é que você precisa ser capaz de acessar essa parte do seu servidor. A vantagem é que ele requer nenhum configurar, configuração ou adicional estresse código / servidor.

<?php       
$url = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
  if (false !== strpos($url,'.php')) {
      die ("Direct access not premitted");
  }
?>

Eu não encontrar as sugestões com .htaccess tão bom, pois pode bloquear outro conteúdo nessa pasta que você pode querer permitir ao usuário o acesso a, esta é a minha solução:

$currentFileInfo = pathinfo(__FILE__);
$requestInfo = pathinfo($_SERVER['REQUEST_URI']);
if($currentFileInfo['basename'] == $requestInfo['basename']){
    // direct access to file
}
if ( ! defined('BASEPATH')) exit('No direct script access allowed');

irá fazer o trabalho suavizar

Você pode usar phpMyAdmin Estilo:

/**
 * block attempts to directly run this script
 */
if (getcwd() == dirname(__FILE__)) {
    die('Attack stopped');
}

isto é o que o Google usa em seus exemplos php ver aqui

if (php_sapi_name() != 'cli') {
  throw new \Exception('This application must be run on the command line.');
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top