0

I have a .js file hosted on domain1.com, but for this to work correctly I need to add a PHP code at the beginning. The reason for this is to bypass some restriction on Safari for my script and it requires me to create a session. The PHP code creates a session through a url to domain2.com. There is no browser redirection or anything, the user stays in the domain1.com. I want to have a single .js file in domain1.com so maybe an AJAX solution is what I need. Here it is:

<?php
session_start();

  if (!isset($_SESSION['isIFrameSessionStarted']))
    {
        $_SESSION['isIFrameSessionStarted'] = 1;
        $redirect = rawurlencode('http://' . "{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
        header('Location: domain2.com/start-session.php?redirect=' . $redirect);


        exit;
    }

?>

The start-session.php file is hosted on domain2.com does not need any changes, it contains this:

<?php
    session_start(); // create the session cookie
    $redirect = rawurldecode($_GET['redirect']);

    header('Location: ' . $redirect); // redirect back to domain 
    exit;
?>
Drakes
  • 23,254
  • 3
  • 51
  • 94
EnexoOnoma
  • 8,454
  • 18
  • 94
  • 179
  • 1
    What's the problem? Put the PHP code into the PHP file. I **must** be missing something because it seems trivial... – pid Jun 03 '15 at 07:52
  • What is it you want to do? Redirect to another page? If you call this with AJAX you won't get redirected. You probably need to pass the URL you want to redirect to to JavaScript and do the redirection there. – putvande Jun 03 '15 at 08:07
  • @putvande Hi, can you show me how please? – EnexoOnoma Jun 03 '15 at 09:17
  • @pid the thing is that I want to have a single js file. and i can't put PHP into that – EnexoOnoma Jun 03 '15 at 09:18
  • Take a look at http://stackoverflow.com/questions/3352576/how-to-embed-php-in-javascript – lmgonzalves Jun 06 '15 at 14:37
  • @Xalloumokkelos Don't really know what you're trying to do but I believe you want to pass php info to js and back to php am I right? and why set the sessions in domain 2 and not on domain 1? – Daniel Jun 06 '15 at 14:38
  • @Daniel yes, the reason is because I want it cross-domain and the session to be created from domain2 – EnexoOnoma Jun 06 '15 at 14:50
  • @Xalloumokkelos look at my answer should work for your case did something similar a while back. Lemme know if you need help implementing it. – Daniel Jun 06 '15 at 14:56
  • Can you run PHP on server 1 or not? And if answer is yes, what is the reason not to use a php file on server 1? – Henrik Jun 08 '15 at 16:09
  • 3
    Could you clarify what you're trying to do, @Xalloumkkelos? Are you trying to import a .js file from domain 1 to domain 2? Run a script from domain 1 through domain 2? Access data from domain 1 not available on domain 2? – Malovich Jun 09 '15 at 14:44
  • @Xalloumokkelos updated my answer – Daniel Jun 10 '15 at 20:42
  • I believe the OP is having the [Safari iframe 3rd-party cookie problem](http://www.mendoweb.be/blog/internet-explorer-safari-third-party-cookie-problem/). He is trying load a page from a different domain in an iframe and wants it to persist the same iframe PHP session across page refreshes. Most older solutions won't work. Here is a tested and [working solution](http://stackoverflow.com/a/30796371/1938889). – Drakes Jun 12 '15 at 14:09
  • If you want to execute the cross domain AJAX then try `dataType=JSONP` – Mitul Jun 12 '15 at 18:11

6 Answers6

7

Let me combine what you requested in comments:

I have a .js file hosted on domain1 ... I want to have a single js file and I can't put PHP into that ... the whole purpose of this is for domain1 to not have any php code or php file. ... The reason is because I want it cross-domain and the session to be created from domain2.

It sounds like your issue might be related to the Safari iFrame session cookie problem, especially because you have if (!isset($_SESSION['isIFrameSessionStarted'])) in one of your code blocks. I will continue with this assumption.

Summary of the problem for other readers:

Upon embeding an IFrame from one domain into a website of a different domain, you will quickly realise that Internet Explorer and Safari are blocking the cookies (and thus the session variables) of the website inside the IFrame (ref).


Attempted solutions that didn't pan out:


My solution:

Essentially, PHP session "hijacking". It works surprisingly well where the above solutions failed. This is the essential solution. Please do any security enhancements* and URL-prettifying you like. Basically, we retrieve the PHP session ID through redirects and pass this to the iframe. Instructions are in the comments.

In your domainA.com head place this:

<script src="session.js"></script>

session.js (on domainA.com):

// Location of the domain B session starter
var sessionScriptURL = "http://domainB.com/start-session.php";
var refQSparam = "phpsessionid";

// Check if we have the phpsessionid in the query string
var phpsessionid = getParameterByName(refQSparam);
if(phpsessionid === null) {
    // Not in the query string, so check if we have it in session storage
    var sessionStore = sessionStorage.getItem(refQSparam);
    if(sessionStore === null) {
        // We have no session storage of the PHP session ID either, redirect to get it
        top.location = sessionScriptURL + "?redirect=" + encodeURIComponent(self.location.href);
    } else {
        // phpsessionid was found in session storage. Retrive it
        phpsessionid = sessionStore;
    }
} else {
    // Save the phpsessionid to session storage for browser refresh
    sessionStorage.setItem(refQSparam, phpsessionid);
    // Optional: Redirect again to remove the extra query string data
}

// Helper to get QS values
function getParameterByName(name) {
    return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null;
}

session-starter.php (on domainB.com):

<?php
session_start(); // create the session cookie
$redirect = rawurldecode($_GET['redirect']);

// redirect back with the php session ID
// Optional: encode this information
$href = $redirect . '?phpsessionid=' . session_id();
header('Location: ' . $href);
exit;

HTML (in the body, on domainA.com):

Append PHP session information to the iframe src.

<script>
document.write('<iframe src="http://domainB.com/embedded-script.php?phpsessionid='+phpsessionid+'"></iframe>');
</script>

embedded-script.php (on domainB.com, in an iframe):

<?php
// Use the phpsessionid passed in
$phpsessionid = rawurldecode($_GET['phpsessionid']);

// REF: http://php.net/manual/en/function.session-id.php
function session_valid_id($session_id) {
    return preg_match('/^[-,a-zA-Z0-9]{1,128}$/', $session_id) > 0;
}
// Check that this is potentially a valid session ID
if(session_valid_id($phpsessionid)) {
    // Set the session to the one obtained in session-start.php
    session_id($phpsessionid);
}
session_start(); // Only call this after session_id()!
// Rest of your code 

*Considerations:

  1. Don't actually use document.write, use jQuery or document selectors.

  2. Encode the PHP session ID

  3. Perform another redirect back to the base URL of domainA.com to remove the ?phpsessionid= in the URL for a cleaner look.

  4. If you decide to call session-starter.php with AJAX instead, you will get a new PHP session ID every time for the same reason. The iframe will successfully use this session ID, but if you open a new page to domainB.com, the session will yet again be different.

Community
  • 1
  • 1
Drakes
  • 23,254
  • 3
  • 51
  • 94
  • why didn't you decide to implement an AJAX solution but took this approach? – Daniel Jun 14 '15 at 13:53
  • @Daniel Two reasons: 1) In the [original question](http://stackoverflow.com/revisions/a5ee5ba5-dfa5-46b8-b727-327e384d84c8/view-source) the OP didn't even talk about AJAX, and 2) with this method the OP can open a new window to domainB's page and the session will still be the same. – Drakes Jun 14 '15 at 13:57
4

If you want to run PHP within a file extended with .js, you can do this by telling your apache web server. Add the following directive to the .htaccess or directly to the apache config:

AddType application/x-httpd-php .js

After this is done, your server will run the included PHP code as soon as the file is requested from the server.


Update:

If you want to use sessions with JavaScript, you can do this with an AJAX solution. For this implement a web service on the server which should store the session values. Programming language for implementation can be PHP or another one which can be run by the web server. Request the web service with JavaScript. Here is an answer with an example.

Community
  • 1
  • 1
Henrik
  • 2,771
  • 1
  • 23
  • 33
3

If you want to redirect in Javascript, you can't use a PHP redirect which you have called from AJAX. You can pass the URL you create in PHP and send it back to JavaScript and do the redirect from there. You can do something like:

PHP:

session_start();

if (!isset($_SESSION['isIFrameSessionStarted'])) {
    $_SESSION['isIFrameSessionStarted'] = 1;
    $redirect = rawurlencode('http://' . "{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
    echo json_encode(array('url' => $redirect));
}

JavaScript:

$.get('phpfile', function(result) {
    if (!result) return;
    var data = JSON.parse(result);
    window.location.href = decodeURIComponent(data.url);
});
putvande
  • 15,068
  • 3
  • 34
  • 50
2

Don't know what you're trying to achieve exactly but let's say you want to go from php to js and back to php you could trying something like this:

Solution 1: Using XMLHttpRequest

In PHP (domain1.com):

<?php 
  $parameter = ""; //If you'll like to add a parameter here
  echo "<script type='text/javascript'>window.addEventListener('DOMContentLoaded',". "function () { goToJS('$paramter');});</script>"; 
?>

In JS:

window.goToJS = function (parameter) {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.onreadystatechange = function () {
            if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
                //You can redirect back to a php file here
                document.location.href = "domain1.com"; 

                //You can view feedback from that php file you sent the stuff to here - just for testing
                alert("feedback" + xmlhttp.responseText);
            }
        }
        xmlhttp.open('GET', 'http://domain2.com/start-session.php?q=' + parameter, true);
        xmlhttp.send();

    }

Not sure about your redirect links and stuff but yeah this should pretty much work. Did something similar a while back

Solution 2: Using ajax

Using ajax you could have a JS script as follows. (type could be POST or GET, Used an example where you sent some json to the php file. Can change the data sent if you properly describe to me what you wish to send. Alternatively could be null also

In JS:

function init_() {
            $.ajax({
                type: 'POST',
                url: 'http://domain2.com/start-session.php',
                data: {json: JSON.stringify(selectedEvent)},
                dataType: 'json'
            }).done(function (data) {
                console.log('done');
                console.log(data);
            }).fail(function (data) {
                console.log('fail');
                console.log(data);
            });
        }

In PHP: Let's say you sent a javascript json to PHP. You could use it in PHP as follows:

<?php

            $status_header = 'HTTP/1.1 ' . 200 . ' ' . 'OK';
            header($status_header);
            header('Content-type: text/javascript');
            $json = json_decode($_POST['json']); //Do whatever you want with the json or data sent
            echo "This is the returned data"; //Echo returned data back to JS or wherever

?>
Daniel
  • 598
  • 1
  • 6
  • 23
  • Hi, thank you but I can not follow the instructions on this. what should I add in redirect.php for example? Is it the code of the first block ? – EnexoOnoma Jun 07 '15 at 19:27
  • @Xalloumokkelos Yes the first block of code is your supposed domain1.com which calls the js function in the second block. In the second block the js would do whatever action in the xmlhttp.open(); bit. Then the redirect.php here should be your domain1.com. Do you follow now? Edited the answer – Daniel Jun 08 '15 at 02:50
  • But the whole purpose of this is to domain1 to not have any php code or php file... – EnexoOnoma Jun 08 '15 at 06:44
  • @Xalloumokkelos doesn't have to have one actually. Your question wasn't quite clear at first that's why I just put it up there. The echoed javascript can be all you put there. Don't necessarily need to wrap it in php tags if your page isn't php. I hope you follow. Do you? Updated my answer to add Ajax since you changed your question slightly – Daniel Jun 08 '15 at 16:59
2

why don't just use script directly (if you put this script on top of file it will wait the script to finish creating session in domain2 anyway. (I guess you have iframe in domain1 that call to domain2?)

<script src="http://domain2.com/start-session.php"></script>
2

USe jquery and jqxhr object for this request, no need send browser to second server, from domain1 you can request to browser load page to init session, and your client never see that.

//include jquery min library and do next code

$(document).ready(function (){     
var jqxhr = $.get( "http://domain2.com/start-session.php", function() {
  alert( "success" ); //some action for success
})
  .done(function() {
    alert( "second success" ); //when all is done (success done)
  })
  .fail(function() {
    alert( "error" ); //some action for error
  })
  .always(function() {
    alert( "finished" ); //some end action for anycase
  });
});

you can delete .done function, .fail function, and always function as you wish. NOTE: ready function is to make sure, that domain1 page completely load, and then run script.

reference https://api.jquery.com/jquery.get/