We have a legacy (php) aplication, accepting file uploads and they are stored at a path depending on the session id. Now we had to provide a very simple API for this webapp, where through an iOS api (iPad) a file upload is performed. We return an url which the customer will open in an embedded webkit window.
Because the sessions from the upload and view actions are different, we thought to grab the session parameter and return it in our response from the file upload. Then the client gets redirected to that url, we set the session id to the previous id and continue to the page the customer can continue the work.
Apparently, nothing I tried works. We use Zend Framework 1, but that shouldn't really matter. I tried:
Setting a Set-Cookie header (this results in a cookie containing two PHPSESSID values)
Use a setcookie("PHPSESSID", $session, 3600) to set the PHPSESSID
Use the Zend http Reponse with a setHeader('Set-Cookie', 'PHPSESSID=....', true)
The last two options just don't do anything, like I didn't set the session at all. How can I solve this? We actually can't touch the legacy code base that much to modify its working and change the way the path resolving works for file uploads.
So, the flow is:
Request to api.myapp.tld -> Response with a string in body -> Open webkit window with this response string as location -> Request is performed -> Response with a Redirect header and a method to set the cookie to something different -> Webkit performs redirect -> Customer gets to a page with same session ID as the first request to api.myapp.tld.
If there is an alternative to set the session id, it would be great.
That's not trivial to debug, but you have some options. I'm not fluent with Zend Framework 1.x, so this is not framework specific (frameworks sometimes add stuff on top), but PHP specific.
In PHP a session is identified by two things:
Name (example: a common default name is PHPSESSID)
ID (that is the random "number")
The Name allows to use multiple sessions at once, while the ID identifies the session in specific.
It sounds a bit you need to use two session IDs in parallel. I suggest you make the script that needs to deal with the legacy session to have another sessions name than your current script.
You can then pass in the legacy/old session id by using the other session name while your current session can remain as is.
I hope this information is helpful. If you have got problems to implement that, please ask.
I ended up by something simpler. The session was related to the path like this /path/to/location/ . $sessionId. When the second session was started, I simply renamed the directory from the old session to the new one. Simple and fast to get this working.
Related
I am currently writing a Magento 2 module that requires me to log customer actions like product views. This action needs to be added for both logged in customers and guest customers. My solution is to use a custom variable (array) in the session for the customer of all product ID's.
To get around full page caching I have implemented a frontend ajax request to log the product views.
I have a controller that when visited will save the product ID in the session. This works as expected when I visit the URL directly, however, when its visited via an AJAX request the saving of the session variable does not work.
I have spent hours trying to debug this, I have been outputting the contents of the session variable and when accessed with AJAX I can see the contents, it's just never updated.
```
public function setGuestCustomerProductView($productId)
{
$guestProductViews = $this->_sessionManager->getGuestProductViews();
$guestProductViews[] = $productId;
$this->_sessionManager->setGuestProductViews($guestProductViews);
return $guestProductViews;
}
```
The AJAX request will always return the contents of the session variable (plus the product ID you are viewing) but never sets the variable. If I visit the URL directly in the same browser the contents are shown and the session variable is updated.
Further AJAX requests show the new session variable data from the direct URL request.
Have I misunderstood something in regards to sessions and AJAX requests? The domain is the same so there is no cross domain issues.
Any help would be appreciated.
UPDATE
I am starting to think this is not a magento 2 issue and it's more of a general Session/AJAX issue.
I decided to test a theory and switch out the SessionManager and use PHP's $_SESSION global variable. This resulted in the same issue so it's not the handler that's the issue.
Further tests concluded the same session ID was being passed and used correctly. While using the SessionManager I called isSessionExists() directly before the set method. This method returned true which checks for not only a valid session ID but also confirms the headers haven't been sent.
I see no reason why this works directly in the browser but not over AJAX. I will continue to investigate unless someone posts and answer I can try out.
SECOND UPDATE
After several failed attempts to get this feature to work I have decided to drop the feature and try a different implementation. As it stands in my module I am not using cookies on the clients side to record the product views and then reading the cookie in PHP. This works perfectly.
I hope my investigations here helps someone in the future.
Background:
I'm developing a website tracker using javascript. Here's how it works:
1) A user visits any domain the tracker script is on "anydomain.com". The script makes a successful ajax call in the background to my master domain "masterdomain.com".
2) When "masterdomain.com" receives a request, the following PSEUDO code is run. It works by checking for an existing session and if one doesnt exist it creates a new one.
The first call appears to be fine because I am able to receive a session ID in a response. However, each successive call to "masterdomain.com" creates a new session. AKA the server doesn't find the "should be" existing session.
Sample PSEUDO Code:
if(session exists)
{
// update timestamp for session
}
else
{
// set a new session for visitor
}
// load template
api(array("accepted"=>session_id),callback);
Some Quick Facts:
1) This does not appear to be a same origin issue (as I am able to communicate with the server fine).
2) I have tried this with cookies/sessions both appear to not be working.
3) I am using codeigniter (sessions are set not to expire on page close). I have also tried using/not using database sessions).
This problem can also be solved if there is another way to uniquely identify a user each time a page loads on a server (not using IP).
Any help would be greatly appreciated as I'm about ready to tear the rest of my hair out of my head!!!! :(
This answer is incomplete in that you'll have to do some additional research, but the easiest way (which is not actually particularly 'easy') to do this is to use Javascript to place a hidden iframe to masterdomain.com, and set up iframe communication (e.g. using postMessage) to retrieve the session from that iframe to your page.
With AJAX calls you can only send/set session cookies if the URL you're calling is on the same domain as your calling script. I think you should create an iframe, call ajax from within and it should work fine. By the way, I have no idea what you are trying to track.
Everything is working fine if all the processing happens on my own site. The session variable get stored and retrieved successfully.
Now I got a third part integration, which is processed via POST data. I have got session_start() called at the first line of each php file.
start_process.php - sets some session variables as follows and calls third party that redirects to response.php
$_SESSION["id"] = $id // Echoing these shows the correct values
$_SESSION["name"]= $name // Echoing these shows the correct values
response.php - This page receives the response from the third party and tries to get the data from session variables
$id = $_SESSION["id"] // This comes out to be blank
$name = $_SESSION["name"] // This comes out to be blank
On my processing page i.e. the response.php, I am trying to retreive back the session values, I don't get the session variables back.
Searching on SO, few post suggest that to check the value of
echo session_id();
which comes to be as different on the first page and the later page coming back to my site. Searching further shows that the value of the following needs to be blank
echo ini_get('session.cookie_domain');
This indeed is blank. Now I am stuck as I see this value as blank, and even though the session is not getting loaded properly.
Can you please suggest what to do next? Any debugging? Any hints to solve this problem?
Update
start_process.php
has a form whose post action is the url to third party site... as
<?php session_start();
$_SESSION["Check"] = "Abc";
echo session_id();
>
<form name="myform" action="http://<ThirdPartyUrl.com>/pathToSomePage.jsp" method="POST">
<!-- some hidden fields with value and some other text fields -->
</form>
respone.php
The third party gives a response in post request again to my response page where I directly test the output of the POST variables and here I am trying to use my session variables
<?php session_start();
echo $_SESSION["Check"];
echo session_id(); // This is different from the one printed in the start_process.php page
?>
I don't think the third party hosting is on the same server, because currently I am on a shared host and the third party definitely has it's own server.
It's hard to know without seeing some more code (how start_process.php is hooking into the third-party code, how the third-party is coming back to response.php). Here are a couple guesses:
Theory 1: third-party code is messing with your session (if hosted on the same server)
Is this third-party integration hosted on your same server? If so, I would suspect that the third-party could be ending/recreating, or otherwise modifying your session.
Theory 2: third-party is redirecting back to your site using a separate domain
Is it possible that you start off at mydomain.com and the third-party redirects back to www.mydomain.com (or something like that)? Even though those two domains look like they should be the same, they are utterly different as far as PHP sessions are concerned, you'll end up with a different session.
I've dealt with a similar problem when working on shopping cart payment gateway integrations. If the response script is ultimately contacted via the browser (i.e. the user is redirected to response.php after they're done on the 3rd party site), the session IDs and cookies will be preserved. If your response script is contacted via a server side request from the 3rd party site, that request is treated as an entirely new session. In that case a lot of integrations allow you to senda "passthrough" variable that will be sent back to your response script along with the rest of the data generated by the 3rd party site. You can use this variable to connect the user's session to the server side request you receive later on (for example you could create a database that relates the two values). Alternatively you could "cheat" the system. If you're passing the response script location along with your request every time, you could build your own passthrough variable into it. So instead of something like
<responseURL>www.mysite.com/response.php</responseURL>
you could send
<responseURL>www.mysite.com/response.php?key=abcd1234</responseURL>
I would recommend setting the key parameter to the session ID directly, so you'd have to build something simple that could translate between the two (like the table I mentioned above).
First of all you need to start a session before to use it. Before assign any value to a session valiable type into your code: session_start(); Do not forget to destroy/unset the session eighter. Hope it will work
Use cookies with some specified expire timings ! it will works well. updated your question with some code so coder can debug it !
Short answer is: find the cookie!
You can loose at domain or directory level. See session_set_cookie_params() specs.
What about the 3rd part. Does response.php requested from the same browser or from another web app, so have it the same cookie? It seems to me that doesn't.
To solve the problem is required to analyze the process steps to determine the place of every execution
If the thirdparty application is calling itselft to the URL of the response and is not a redirection into the client the sessions are not the same.
Example:
Client navigates to start_process.php and a session is created for client
start_process.php calls the thirdParty
Thirdparty app calls response.php and a session for thirdparty is created
Is important to check that the session ID is maintained by the client cookie and validated in the server. The client that starts the process and the thirdparty are diferent "clients" of the app with their own sessions.
Diagram example that shows you are probably doing based on your question.
Probably you can't call the third party directly from the client. On the client call a page on your host that calls the third party and capture the response (for example using curl)
Diagram example:
I have a web application and I want to make it run offline as well. In this application I just have a form and I am using PHP for submitting it. I am using a manifest.php file like the one described in http://building-iphone-apps.labs.oreilly.com/ch06.html .
The problem is that I need somehow to add the parameters from the form in the manifest, for caching the right file, for example the file welcome.php?name=aaaa and not the welcome.php . So I need to use a GET for the name in the manifest.php. But if I understood well the manifest file is created in the beginning before the form is submitted so the value on "name" is empty.
Is there a way to add these parameters in my manifest file for running the application offline as well?
Thanks
The only way you can do that is to list the files with their parameters in the manifest, so you would have to know all the possible parameters in advance and then use your manifest.php to spit them out, ending up with a manifest file that looks something like this:
CACHE MANIFEST
welcome.php?name=aaaa
welcome.php?name=aaab
welcome.php?name=aaac
...thousands more lines...
welcome.php?name=zzzz
NETWORK:
welcome.php
However, I strongly recommend you don't do it this way if (as it looks like) you want to present a personalised welcome page to the user. With this approach every user will download every welcome page, even though they only need to see one of them.
There are two approaches I think will work better:
1: Deliver personalised pages
If only thing which changes is this page, force the user to logon before accessing the welcome.php page, then use a session variable instead of a query parameter to deliver the personalised page. You then just need to specify welcome.php in your manifest and every user will cache one personalised version.
2: Write a full offline app
If your web app is going to have user specific data at every step you need to break down what are the common application components and what is the user data, and serve them separately. If your app is going to do anything offline it's going to be doing it with JavaScript, you should therefore use JavaScript to update the page in the browser rather than generating entire pages on the server side with PHP.
Most of your PHP pages are basically going to be templates which you will load with user data through JavaScript (you can still populate them the 'old' way for users who don't have offline capability in the browser). You will have at least one PHP page which delivers data in response to AJAX requests. For this approach you're going to need to learn about Local Storage and the various JavaScript APIs for managing the cache and detecting offline state. Once the user decides to install the offline version of your web app you download all of that user's data and put it in Local Storage, then use that data to update each page as it loads when the user is offline. Any changes made then need to be synced back to the server when the user is back online.
Due to applciation cache is loaded after the page it references to. You have to reload the cache by applicatonCache.update() when the parameters are available.
The trick to inject the parameters into the the manifest is to set cookies before invoking update(). Your serverside script gets the cookies and can generate the appropriate manifest content.
I'm building a PHP-based web app and am integrating a Flash-based charting engine. The Flash chart needs to make a AJAX request for its data. This request fails because it is seen as a new user agent and doesn't contain the PHP session cookie to identify it. So, it gets redirected to the login page.
I've read a few hacks to make this work, including supplying the session ID on the querystring, but that opens up security holes. How can I get Flash and PHP to share cookie-based session state automatically and stay secure?
In IE it will work naively. In firefox, the only way to achieve this is to POST the session id into the flash script (the php processor that is), and have it restore the session from that.
If the session cookie is initiated early enough, then it should be OK. I've had a similar problem with cookies shared between JavaScript AJAX and Flash requests (if you want to call that AJAX too, go ahead :-) ), and we solved them by making sure the JavaSCript finished the request that initiated the cookie early enough so that when the Flash sent the request, the browser already had the session cookie.
Also making sure the cookie path was set to "/" was a good idea.
That being said, if you can't get it to work - as dirkgently said - you can store the information in the HTML DOM using a JavaScript AJAX call, and then fetch it from the Flash object using an ExternalInterface call. But do make sure to set at least "allowScriptAccess=sameDomain" on your Flash object
You should be aware that transmitting a session ID in a Cookie: header, or in the argument field of the GET HTTP directive is of no different security.
Use ExternalInterface to talk to the Flex chart. Some browser related information can be passed around via the LoaderContext and BrowserManager classes as well. Dig in a bit into the AS3 documentation.
you can try and send to php 2 parameters one session_id and a second one that is an key that combines some information from the client ( ex ip ) and encrypt it with a key stored on the server and on the request from flash you check to see the second paramaters matches the client request, this way if somebody trys to do a session stealing they cant because they will not match the second param