0

How to use php to outout an js file and detect if file was embed or connect directly I want to use php to output some js file It's very simple like :

header(Content-Type: text/javascript);

But I want to know if the file was embed inside a web page like:

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

or was directly open in a browser at http://foo.com/foo.js Thanks

hichris123
  • 10,145
  • 15
  • 56
  • 70
thangngoc89
  • 1,400
  • 11
  • 14

2 Answers2

0

You can't tell the difference on the receiving end. The requests are the same in both cases and the web server is going to serve foo.js exactly the same way. If you control the HTML page where the javascript is embedded, you could construct a token/hash scheme (much like you might do to prevent CSRF) to verify that the requests for the file are not direct requests. Ex:

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

The problem with doing this though is that it includes the overhead of having the PHP parser generate your javascript, rather than it just being a static file served directly by the web server. It may also have an effect on browser caching.

Leo Bedrosian
  • 3,659
  • 2
  • 18
  • 22
  • Yes. I'm doing it to prevent CSRF. It's a little difficult If it's a direct requests, It only show location.assign("foo.com"); – thangngoc89 Aug 30 '14 at 17:55
0

You could use your .htaccess to reroute requests to a PHP file like: (I'm not testing it, but it should work, I think)

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]

Your .htaccess file generally will go at the root of your site, or you could put it in the folder containing all your javascript files.

Then in your js_handler.php file, you could do some sort of check.
Easiest (but not secure) option would be:

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

To get $header see this post.
A much more thorough route would be to use a randomly generated access key and verify against that. You could have a cron job generate a new key every five minutes or so and use SQL or write it to a file. For example:

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

Then when you deliver an HTML page (assuming you're doing it via 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>

Then in 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
}

For the location of the script use $_SERVER['REQUEST_URI']. You should be able to just include the javascript file and let the script terminate. You may need to set the headers, though. I'm not totally sure and can't test it right now.

Community
  • 1
  • 1
Reed
  • 14,703
  • 8
  • 66
  • 110
  • 1
    Request headers can easily be forged (they are created by the requester after all) so that's not a fool proof way to restrict access, if it's really important to do so. Just an FYI. – Leo Bedrosian Aug 30 '14 at 17:27
  • 1
    I know. I mentioned that, I just couldn't think of the word 'forged' for some reason. I'll improve my answer later to cover a more secure route. – Reed Aug 30 '14 at 17:43
  • @Jakar what the .htaccess file do? I don't really know it's mean. If it redirect all .js to js_handler.php so how can I know which file was requested? – thangngoc89 Aug 30 '14 at 17:51
  • @NguyễnĐăngKhoa I updated my answer and hope it helps. If you have any questions, I won't be able to respond until tomorrow. – Reed Aug 30 '14 at 19:04
  • I think at .htaccess file there are something wrong. I but your code to domain.com/js/.htaccess there is a domain.com/js/js_handler.php in that directory try to request domain.com/js/foo.js => 500 internal server error This is my .htaccess file Options -MultiViews RewriteEngine on RewriteBase / RewriteCond %{REQUEST_FILENAME} !-d #not a directory RewriteCond %{REQUEST_URI} ^(.+)\.js$ RewriteRule ^(.+)$ /js_handler.php [QSA] – thangngoc89 Aug 31 '14 at 07:25
  • Try removing the comments (the part after `#`) and it should work. Also for the `RewriteRule`, it should be `[L, QSA]` instead of `QSA`. I updated my answer to represent these changes as well. – Reed Sep 02 '14 at 19:34
  • It's also possible that if you have a `.htaccess` file in a parent directory, that could cause a problem too. – Reed Sep 02 '14 at 19:35