2013-01-20 105 views
3

我有一個ADMIN腳本。

PHP保護目錄免受直接URL訪問

admin/index.php 

的所有活動都通過這個index.php文件來完成。
用戶在訪問程序功能之前正在登錄。
$_SESSION['user_authenticated']已創建並設置爲true

admin/template/.. 

此文件夾包含imagescssjavascript文件。
它們僅在此ADMIN內使用。 (僅在後端)

問題:

我需要admin/template/..目錄中的所有內容反對直接訪問保護。
它應該僅適用於已通過身份驗證的用戶。

我想必須有一個.htaccess將請求重定向到check_session_auth_variable.php,看起來如果$_SESSION['user_authenticated']重定向到請求的文件拋出一個404錯誤

我知道最好的選擇是將目錄放置在Web根目錄之外,但在我的情況下,我需要保持目錄結構不變,無需修改。

+0

最好的答案是:**不」做。 **開放訪問css/js文件,保護php文件,使用'拒絕所有'來保護子目錄。很多流行的WordPress博客都可以打開'/ wp_admin/*'([example](http://www.gizmodo.co.uk/wp-login.php?redirect_to=http%3A%2F%2Fwww.gizmodo)。 co.uk%2Fwp-admin%2F&reauth = 1)),只要在你的php文件中沒有安全問題,它確實沒關係 – Peter

+0

爲什麼當未經授權的人會看到任何圖像,樣式表或JavaScript文件?其中是否有敏感數據? – Gumbo

+0

@彼得Szymkowski謝謝你的答案。並且感謝你使用'deny from all'的想法,如果有必要的話,我認爲它可以和'allow from IP'一起使用。 – acoder

回答

1

管理員/的.htaccess:

RewriteCond %{REQUEST_FILENAME} !check_auth.php 
RewriteCond %{REQUEST_FILENAME} -f 
RewriteRule .* check_auth.php?file=$0 [QSA,L] # pass everything thru php 

管理/ check_auth.php:

$file = $_GET['file']; 
if($_SESSION['user_authenticated']) { 
    // please mind you need to add extra security checks here (see comments below) 
    readfile($file); // if it's php include it. you may need to extend this code 
}else{ 
    // bad auth error 
} 
+5

關於這個過程的注意事項:在網站流量高時通常不是一個好主意,因爲啓動一個PHP線程來處理一個簡單的文件讀取的開銷是waaaaaaay比讓Apache/IIS/etc服務更多內容是靜態的。所以,只要記住,如果你要在高流量的管理面板上這樣做。當涉及到管理面板的圖形/ JS文件時,通過默默無聞的安全性通常就足夠了。關閉admin文件夾的目錄列表(無論如何你都應該這樣做)。在JS/HTML代碼中不應該有任何「安全」的東西 – Brian

+1

@Brian同意,這是高流量管理面板的壞主意。我們可以始終做的事情很少:1.將管理面板限制爲少數ips。 2.清除漏洞中的js代碼3.更改管理面板目錄名稱,如「/ admin6234123312」:] – Peter

+3

只是另一個說明,顯然你會想在執行'readfile()'之前進行一些額外的安全檢查檔案出來。由於PHP/Apache很可能在服務器上訪問更多文件,這使得腳本可以被利用來訪問用戶應該無法訪問的文件。如果有人劫持管理員會話,他們可以在技術上使用該文件以純文本格式(用戶名,密碼,數據庫信息等)讀取您網站上的任何文件。只要他們知道文件路徑。 – Brian

1

好吧,這裏是我的回答 - 這是真的,最好的答案是「沒有'。但是圖像/ js/css在開發過程中比較重要(在實時公開之前)以及客戶端預覽指示我們不能執行基於IP的apache規則。因此,(,稍作修改,從上面)的規則是

RewriteEngine On 

# Exclude the public and error directories from authentication 
RewriteRule ^(public|error)($|/) - [L] 

# Perform authentication via php 
RewriteCond %{REQUEST_FILENAME} !auth.php 
RewriteCond %{REQUEST_FILENAME} -f 
RewriteRule .* auth.php?requested_file=$0 [QSA,L] 

(因爲我需要幾個子目錄,其中內容確實是公開的,寫着:在登錄頁上使用的圖片/ CSS/JS)

和相關的PHP如下;對於

 if($authenticated){ 
      if($extension == 'php'){  

       call_user_func(function(){ 

        $file_name = func_get_arg(0); 

        $path = getcwd(); 
        chdir(pathinfo($file_name,PATHINFO_DIRNAME)); 
        return include($file_name); 
        chdir($path); 

       }, $file_name); 

      } else { 

       //set cache headers so the browsers don't have to refresh all the 
       // static content 
       header_remove('X-Powered-By'); 
       header_remove('Transfer-Encoding'); 
       header_remove('Cache-Control'); 
       header_remove('Pragma'); 
       header_remove('Expires'); 
       //header('Expires:'); 

       header('Content-type: '.$mime_type); 
       readfile($file_name); 
      } 
     } 

這樣做是執行使用call_user_func()停止命名空間污染,include()執行PHP PHP和chdir()以確保腳本得到正確的當前工作目錄。

這是'容易'的一部分;內容頭文件和MIME類型必須被「猜到」(我用finfo來表示MIME類型,但它在2013年有一個bug,這隻會加劇這個問題),但即使是apache也不能100%正確地做到這一點...

然後刪除圖像的緩存控制頭,否則你不僅可以經常PHP頁面,以及...

我只想說;你只需要,如果你有厚厚的管道和很多你並不需要的CPU週期來做到這一點...

0

我通常使用這個

$redi_ext = $_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']; 
$php_verify = strpos($redi_ext, ".php"); 
if($php_verify !== false){ header('location: PAGE_NOT_FOUND_URL'); }