2013-01-20 69 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'); }