سؤال

لدي ملف php سأستخدمه حصريًا كملف تضمين.لذلك أرغب في إلقاء خطأ بدلاً من تنفيذه عند الوصول إليه مباشرةً عن طريق كتابة عنوان URL بدلاً من تضمينه.

أحتاج في الأساس إلى إجراء فحص كما يلي في ملف php:

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

هل هناك طريقة سهلة للقيام بذلك؟

هل كانت مفيدة؟

المحلول

وأسهل طريقة ل"التطبيق PHP تعمل على ملقم Apache التي قد تكون أو لا السيطرة الكاملة" عام الوضع هو وضع يشمل بك في دليل ومنع الوصول إلى هذا الدليل في ملف htaccess الخاص بك. لإنقاذ الناس عناء غوغلينغ، إذا كنت تستخدم أباتشي، وضعت هذا في ملف يسمى "هتكس" في الدليل الذي لا تريد أن تكون في متناول:

Deny from all

إذا كان لديك بالفعل السيطرة الكاملة على الخادم (أكثر شيوعا في هذه الأيام حتى لتطبيقات قليلا مما كانت عليه عندما كنت أول ما كتب هذا الجواب)، وأفضل نهج هو التمسك الملفات التي تريد حمايتها من خارج الدليل أن خادم الويب الخاص بك يقضي منها. حتى إذا كان التطبيق الخاص بك هو في /srv/YourApp/، تعيين خادم لخدمة الملفات من /srv/YourApp/app/ ووضع يضم في /srv/YourApp/includes، حتى لا يكون هناك حرفيا لا أي URL التي يمكن الوصول إليها.

نصائح أخرى

وهذا إضافة إلى الصفحة التي تريد إدراجها فقط

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

وبعد ذلك على الصفحات التي تتضمن أنه إضافة

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

ولدي ملف أنني بحاجة إلى التصرف بشكل مختلف عندما يكون تضمينه مقابل عندما يكون الوصول إليها مباشرة (أساسا print() مقابل return()) وإليك بعض التعليمات البرمجية المعدلة:

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

وملف يتم الوصول إليها دائما ملف شملت، وبالتالي == 1.

وأفضل طريقة لمنع الوصول المباشر إلى الملفات هي لوضعها خارج جذر المستند خادم الويب (عادة مستوى واحد أعلاه). لا يزال بإمكانك تضمينها، ولكن ليس هناك إمكانية للشخص الوصول إليها من خلال طلب HTTP.

وأنا عادة يذهب كل في طريقه، وإخضاع كافة ملفات PHP بلدي خارج جذر المستند جانبا من في ملف التمهيد - أ index.php الوحيد في جذر المستند الذي يبدأ توجيه كامل الموقع / تطبيق

وبديل (أو تكمل) إلى حل تشاك ستكون لمنع الوصول إلى الملفات مطابقة نمط معين عن طريق وضع شيء من هذا القبيل في ملف .htaccess الخاص بك

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

1:التحقق من عدد الملفات المضمنة

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

منطق: يتم الخروج من PHP إذا لم يتم استيفاء الحد الأدنى لعدد التضمين.لاحظ أنه قبل PHP5، لم تكن الصفحة الأساسية تعتبر تضمينًا.


2:تحديد والتحقق من ثابت عالمي

// 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');

منطق: إذا لم يتم تعريف الثابت، فلن يبدأ التنفيذ من الصفحة الأساسية، وسيتوقف PHP عن التنفيذ.


3:ترخيص العنوان البعيد

// 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');

عيب هذه الطريقة هو التنفيذ المعزول، ما لم يتم توفير رمز جلسة العمل مع الطلب الداخلي.تحقق عبر عنوان الاسترجاع في حالة تكوين خادم واحد، أو القائمة البيضاء للعناوين لبنية أساسية متعددة الخوادم أو خادم متوازن التحميل.


4:ترخيص الرمز المميز

كما هو الحال مع الطريقة السابقة، يمكن استخدام GET أو POST لتمرير رمز التفويض إلى ملف التضمين:

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

طريقة فوضوية للغاية، ولكنها أيضًا ربما تكون الأكثر أمانًا وتنوعًا في نفس الوقت، عند استخدامها بالطريقة الصحيحة.


5:تكوين محدد لخادم الويب

تسمح لك معظم الخوادم بتعيين أذونات للملفات أو الأدلة الفردية.يمكنك وضع جميع تضميناتك في هذه الأدلة المقيدة، وتهيئة الخادم لرفضها.

على سبيل المثال، في APACHE، يتم تخزين التكوين في ملف .htaccess ملف.درس تعليمي هنا.

ملحوظة ومع ذلك، لا أوصي بهذه التكوينات الخاصة بالخادم لأنها سيئة لقابلية النقل عبر خوادم الويب المختلفة.في مثل هذه الحالات حيث تكون خوارزمية الرفض معقدة أو تكون قائمة الدلائل المرفوضة كبيرة إلى حد ما، فقد يؤدي ذلك إلى جعل جلسات إعادة التكوين مروعة إلى حد ما.في النهاية من الأفضل التعامل مع هذا في الكود.


6:وضع التضمينات في دليل آمن خارج جذر الموقع

الأقل تفضيلاً بسبب قيود الوصول في بيئات الخادم، ولكنها طريقة قوية إلى حد ما إذا كان لديك حق الوصول إلى نظام الملفات.

//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");

منطق:

  • لا يمكن للمستخدم طلب أي ملف خارج htdocs المجلد لأن الروابط ستكون خارج نطاق نظام عناوين موقع الويب.
  • يصل خادم php إلى نظام الملفات محليًا، وبالتالي يمكنه الوصول إلى الملفات الموجودة على جهاز الكمبيوتر تمامًا كما يفعل البرنامج العادي مع الامتيازات المطلوبة.
  • من خلال وضع ملفات التضمين في هذا الدليل، يمكنك التأكد من وصول خادم php إليها، بينما يتم رفض الارتباط السريع للمستخدم.
  • حتى لو لم يتم تكوين الوصول إلى نظام الملفات الخاص بخادم الويب بشكل صحيح، فإن هذه الطريقة ستمنع هذه الملفات من أن تصبح عامة عن طريق الخطأ.

يرجى عذر اصطلاحات الترميز غير التقليدية الخاصة بي.هو موضع تقدير أي ردود فعل.

في الواقع نصيحتي هي القيام بكل هذه أفضل الممارسات.

  • ضع المستندات خارج Webroot أو في دليل تم رفض الوصول إليه من قبل خادم الويب و
  • استخدم تعريفًا في مستنداتك المرئية التي تتحقق منها المستندات المخفية:
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

بهذه الطريقة، إذا أصبحت الملفات في غير مكانها بطريقة أو بأخرى (عملية بروتوكول نقل الملفات الخاطئة) فإنها تظل محمية.

وكان لي هذه المشكلة مرة واحدة، حلها مع:

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

ولكن الحل الأمثل هو وضع الملف خارج جذر المستند خادم الويب، كما هو مذكور في anwser آخر.

وأنت تريد إنشاء التطبيق مع نقطة مدخل واحد على نحو أفضل، ينبغي التوصل أي كافة الملفات من index.php

ومكان هذا في index.php

define(A,true);

ويجب أن يعمل هذا الاختيار في كل ملف مرتبط (عبر تتطلب أو تضمين)

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

وأسهل طريقة هي وضع بعض المتغيرات في الملف الذي يدعو تشمل، مثل

$including = true;

وبعد ذلك في الملف الذي يجري المدرجة، تحقق للمتغير

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

وماذا جملة! لم يتم تحديد ثابت في ملف الجذر والتحقق إذا تم تعريف نفسه في الملفات المدرجة.

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

وأو آخر

ويمكن للمرء أن منع جميع الملفات بعيدا عن متناول طلب HTTP عن طريق وضعها خارج الدليل الجاسوس حيث أن معظم الأطر مثل كود إغنيتر التوصية.

وأو حتى عن طريق وضع ملف .htaccess داخل تشمل قواعد المجلد والكتابة، يمكنك منع الوصول المباشر.

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

وأردت لتقييد الوصول إلى <القوي> PHP ملف مباشرة، ولكن أيضا أن تكون قادرة على تسميته عبر jQuery $.ajax (XMLHttpRequest). هنا هو ما عملت بالنسبة لي.

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;
    }
}

إلى جانب طريقة .htaccess، رأيت نمطًا مفيدًا في أطر عمل مختلفة، على سبيل المثال في Ruby on Rails.لديهم دليل pub/ منفصل في الدليل الجذر للتطبيق وتوجد أدلة المكتبة في الدلائل في المجلد نفس المستوى كحانة/.شيء من هذا القبيل (ليس مثاليًا، لكنك حصلت على الفكرة):

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

قمت بإعداد خادم الويب الخاص بك لاستخدام pub/ كجذر للمستند.يوفر هذا حماية أفضل للنصوص البرمجية الخاصة بك:وبينما يمكنهم الوصول من جذر المستند لتحميل المكونات الضرورية، فمن المستحيل الوصول إلى المكونات من الإنترنت.فائدة أخرى إلى جانب الأمن هي أن كل شيء في مكان واحد.

يعد هذا الإعداد أفضل من مجرد إنشاء عمليات فحص في كل ملف مضمن لأن رسالة "الوصول غير مسموح به" هي دليل للمهاجمين، وهو أفضل من تكوين .htaccess لأنه لا يستند إلى القائمة البيضاء:إذا أخطأت في امتدادات الملفات، فلن تكون مرئية في lib/، conf/ وما إلى ذلك.الدلائل.

إذا بتعبير أدق، يجب عليك استخدام هذا الشرط:

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

get_included_files () يعود مجموعة المفهرسة التي تحتوي على أسماء جميع الملفات المضمنة (إذا beign تنفيذ ملف ثم أدرج واسمها في مجموعة). لذلك، عند الوصول إلى الملف مباشرة، اسمها هو الأول في مجموعة، تم تضمين كافة الملفات الأخرى في مجموعة.

<?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>");
}
?>

ضع التعليمات البرمجية أعلاه في الجزء العلوي من ملف PHP وشملت الخاصة بك.

مثال:

<?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
?>

ويتم استخدام التعليمات البرمجية التالية في Flatnux CMS ( http://flatnux.altervista.org ):

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

ولقد وجدت هذا الحل فب فقط والثوابت التي تعمل مع كل من http و المبادرة القطرية:

وتحديد وظيفة:

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

واستدعاء دالة في الملف الذي تريد منع الوصول المباشر إلى:

forbidDirectAccess(__FILE__);

ومعظم الحلول المذكورة أعلاه على هذا السؤال لا تعمل في وضع مؤشرها.

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

إجابتي مختلفة إلى حد ما في النهج ولكنها تتضمن العديد من الإجابات المقدمة هنا.أوصي باتباع نهج متعدد الجوانب:

  1. .htaccess وقيود Apache بالتأكيد
  2. defined('_SOMECONSTANT') or die('Hackers! Be gone!');

لكن ال defined or die النهج لديه عدد من الإخفاقات.أولاً، من الصعب جدًا اختبار الافتراضات وتصحيح الأخطاء بها.ثانيًا، يتضمن الأمر إعادة هيكلة مرعبة ومملة للعقل إذا غيرت رأيك."العثور على واستبدال!" قول انت.نعم، ولكن ما مدى تأكدك من أنه مكتوب بنفس الطريقة في كل مكان، هممم؟الآن اضرب ذلك بآلاف الملفات...س.س

ثم هناك .htaccess.ماذا يحدث إذا تم توزيع الكود الخاص بك على المواقع التي لا يكون فيها المسؤول دقيقًا جدًا؟إذا كنت تعتمد فقط على .htaccess لتأمين ملفاتك، فستحتاج أيضًا إلى أ) نسخة احتياطية، ب) علبة مناديل لتجفيف دموعك، ج) طفاية حريق لإطفاء النيران في جميع رسائل الكراهية من الناس باستخدام التعليمات البرمجية الخاصة بك.

لذلك أعلم أن السؤال يطرح "الأسهل"، لكنني أعتقد أن ما يستدعيه هذا هو المزيد من "الترميز الدفاعي".

ما أقترحه هو:

  1. قبل أي من البرامج النصية الخاصة بك require('ifyoulieyougonnadie.php'); (لا include() وكبديل ل defined or die)
  2. في ifyoulieyougonnadie.php, ، قم ببعض الأشياء المنطقية - تحقق من وجود ثوابت مختلفة، واستدعاء البرنامج النصي، واختبار المضيف المحلي وما شابه - ثم قم بتنفيذ ملف die(), throw new Exception, 403, ، إلخ.

    أقوم بإنشاء إطار العمل الخاص بي باستخدام نقطتي دخول محتملتين - Index.php الرئيسي (إطار عمل Joomla) وajaxrouter.php (إطار العمل الخاص بي) - لذا اعتمادًا على نقطة الإدخال، أتحقق من أشياء مختلفة.إذا كان الطلب ل ifyoulieyougonnadie.php لا يأتي من أحد هذين الملفين، أعلم أنه يتم تنفيذ خدع!

    ولكن ماذا لو أضفت نقطة دخول جديدة؟لا شكر على واجب.أنا فقط أتغير ifyoulieyougonnadie.php وأنا منظم، بالإضافة إلى عدم وجود "بحث واستبدال".مرحا!

    ماذا لو قررت نقل بعض البرامج النصية الخاصة بي لإنشاء إطار عمل مختلف لا يحتوي على نفس الثوابت defined()؟...مرحا!^_^

لقد وجدت أن هذه الإستراتيجية تجعل التطوير أكثر متعة وأقل بكثير:

/**
 * 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();

ونفعل شيئا مثل:

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

ويمكنك استخدام الطريقة التالية أدناه على الرغم من أنها لديها عيب، لأنها يمكن أن تكون مزورة، إلا إذا كان يمكنك إضافة خط آخر من التعليمات البرمجية للتأكد من أن الطلب لا يأتي إلا من الخادم الخاص بك إما عن طريق استخدام جافا سكريبت. يمكنك وضع هذا الرمز في القسم الجسم من التعليمات البرمجية HTML الخاصة بك، لذلك يظهر الخطأ هناك.

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

ضع كود HTML الآخرين هنا

<? } ?>

وإنهاء مثل هذا، وبالتالي فإن الناتج من الخطأ سوف تظهر دائما داخل القسم الجسم، وإذا كان هذا كيف تريد أن تكون.

وأقترح أن لا تستخدم من $_SERVER لأسباب أمنية.
يمكنك استخدام متغير مثل $root=true; في الملف الأول الذي شمل بعضها البعض.
واستخدام isset($root) تبدأ في الملف الثاني الذي يتم تضمين.

وماذا يمكنك أيضا القيام به هو حماية كلمة السر الدليل والحفاظ على جميع النصوص الخاص بي هناك، فكورسي باستثناء ملف index.php، كما في وقت تشمل لن تكون هناك حاجة كلمة السر كما ستكون هناك حاجة فقط ل http التمكن من. ما سوف تفعله هو ان نقدم لك أيضا خيار للوصول إلى النصوص الخاصة بك في حال كنت ترغب في ذلك كما سيكون لديك كلمة مرور للوصول إلى الدليل. سوف تحتاج إلى ملف هتكس الإعداد لدليل وملف .htpasswd لمصادقة المستخدم.

وكذلك، يمكنك أيضا استخدام أي من الحلول المذكورة أعلاه في حال كنت تشعر بأنك لا تحتاج إلى الوصول إلى هذه الملفات عادة لأنه يمكنك دائما الوصول إليها من خلال وحة التحكم وغيرها.

ويساعد هذا الأمل

وأسهل طريقة لتخزين يشمل بك خارج الدليل على شبكة الإنترنت. بهذه الطريقة على الملقم الوصول إليها ولكن لا آلة خارجية. الجانب السلبي الوحيد هو عليك أن تكون قادرا على الوصول إلى هذا الجزء من الخادم الخاص بك. الاتجاه الصعودي هو أنه لا يتطلب أي إعداد، التكوين، أو إضافي الإجهاد كود / الخادم.

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

ولم أجد الاقتراحات مع هتكس جيدة جدا لأنه قد منع المحتويات الأخرى في هذا المجلد والتي قد ترغب في السماح للمستخدم الوصول إلى ل، هذا هو بلدي الحل:

$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');

وسوف قيام بهذه المهمة على نحو سلس

ويمكنك استخدام بريس نمط:

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

وهذا هو ما يستخدم جوجل في الأمثلة فب على نرى هنا

if (php_sapi_name() != 'cli') {
  throw new \Exception('This application must be run on the command line.');
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top