如何使用php输出js文件并检测文件是否嵌入或直接打开

时间:2014-08-30 16:19:26

标签: php

如何使用php输出js文件并检测文件是否嵌入或直接连接 我想用php输出一些js文件 它非常简单:

header(Content-Type: text/javascript);

但我想知道该文件是否嵌入在以下网页中:

<script src='http://foo.com/foo.js'></script>

或直接在http://foo.com/foo.js的浏览器中打开 感谢

2 个答案:

答案 0 :(得分:0)

你无法区分接收端的区别。两种情况下的请求都是相同的,Web服务器将以完全相同的方式提供foo.js。如果您控制嵌入了javascript的HTML页面,您可以构造一个令牌/哈希方案(就像您可能做的那样,以防止CSRF)来验证对该文件的请求不是直接请求。例如:

<script src="http://foo.com/foogenerator.js.php?k=SOMERANDOMVALUE"></script>

这样做的问题在于它包含让PHP解析器生成你的javascript的开销,而不是它只是一个由Web服务器直接提供的静态文件。它也可能对浏览器缓存产生影响。

答案 1 :(得分:0)

您可以使用.htaccess将请求重新路由到PHP文件,例如:(我没有测试它,但我认为它应该可以工作)

Options -MultiViews
RewriteEngine on

RewriteBase /
#if not a directory and ends in .js, then rewrite URL to /dir/js_handler.php and append the query string
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteCond %{REQUEST_URI} \.js$
RewriteRule ^(.+)$ /dir/js_handler.php [L,QSA]

您的.htaccess文件通常会放在您网站的根目录下,或者您可以将其放在包含所有javascript文件的文件夹中。

然后在js_handler.php文件中,您可以进行某种检查 最简单(但不安全)的选择是:

if ($header['Referer']=='mydomain.com'){
    //it was requested by loading the HTML page
} else {
    //it was requested directly
}

$headerthis post 更彻底的方法是使用随机生成的访问密钥并对其进行验证。您可以让cron作业每五分钟左右生成一个新密钥,并使用SQL或将其写入文件。例如:

$file_path = //some path
$randKey = generateRandomKey();
$keyArray = json_decode(file_get_contents($file_path),true);
$keyArray[1] = $keyArray[0];//move the first element to the 2nd.
$keyArray[0] = $randKey; //set the first element to $randKey
file_put_contents($file_path,json_encode($keyArray) );

然后,当您提供HTML页面时(假设您通过PHP进行):

<?php
    $keyArray = json_decode(file_get_contents($file_path),true);
    $randKey = $keyArray[0]; 
?>
<head>
    <script type="text/javascript" 
            src="/path/to/myscript.js?secret=<?=$randKey?> ></script>
</head>

然后在js_handler.php

$keyArray = json_decode(file_get_contents($file_path),true);
if (in_array($_GET['secret'],$keyArray){
    //deliver the js file
} else {
    //deliver 404 page
}

对于脚本的位置,请使用$_SERVER['REQUEST_URI']。您应该只能include javascript文件并让脚本终止。但是,您可能需要设置标题。我不完全确定,现在无法对其进行测试。