Getting SESSION to work after redirect - php

I am new to PHP and even newer to SESSIONS
I am working with the Instagram API and I am successfully able to authorize an app, and redirect to a page to display content.
My main folder is called Monkey and it has a sub folder called Instagram.
MY callback url for instagram is success.php located in the instagram folder. When I successfully retrieve an access token from Instagram it redirects to the index file in the Monkey folder.
On my success page, I am creating an array full of data called instaArray. I am trying to pass the array from the success.php in the instagram folder, to the index.php in the monkey folder.
My redirect is simply
header( 'Location: ../index.php' );
Because I am new with sessions, I guess I am doing something wrong. I figured it was straight forward, but I suppose not ha.
On the success.php page, after I build the array I have this
session_start();
$_SESSION['instagram'] = $instaArray;
I thought that should create a session that holds my array InstaArray.
Then, on the index.php page in Monkey, I have this
<?php
session_start();
$get_instagram = $_SESSION['instagram'];
print_r($get_instagram);
?>
But absolutely nothing happens. I've even tried to set the session instagram to a simple numerical value or 1, $_SESSION['instagram'] = 1; and get that on the index page, and it doesn't work either.
Am I doing something horribly, terribly wrong? I've read up on sessions, but because it's new, it's still a little confusing.
Thanks for the help, and I hope I was able to explain everything properly.
EDIT: Here is my success.php page in full
<?php
require 'src/db.php';
require 'src/instagram.class.php';
require 'src/instagram.config.php';
// Receive OAuth code parameter
$code = $_GET['code'];
// Check whether the user has granted access
if (true === isset($code)) {
// Receive OAuth token object
$data = $instagram->getOAuthToken($code);
// Take a look at the API response
$username = $data->user->username;
$fullname = $data->user->full_name;
$id = $data->user->id;
$token = $data->access_token;
$user_id = mysql_query("select instagram_id from users where instagram_id='$id'");
if(mysql_num_rows($user_id) == 0) {
mysql_query("insert into users(instagram_username,instagram_name,instagram_id,instagram_access_token) values('$username','$fullname','$id','$token')");
}
//Set Cookie
$Month = 2592000 + time();
setcookie(instagram, $id, $Month);
// Set user access token
$instagram->setAccessToken($token);
// Retrive Data
$instaData = $instagram->getUserFeed();
// Create Instagram Array
$instaArray = array();
$count = 0;
// For each Instagram Post
foreach ($instaData->data as $post) {
$instaArray[$count]['post_id'] = $post->id;
$instaArray[$count]['name'] = $post->user->username;
$instaArray[$count]['profile_img'] = $post->user->profile-picture;
$instaArray[$count]['img_url'] = $post->images->standard_resolution->url;
$instaArray[$count]['caption'] = $post->caption->text;
$instaArray[$count]['like_count'] = $post->likes->count;
$instaArray[$count]['comment_count'] = $post->comments->count;
$instaArray[$count]['created_time'] = $post->created_time; //Unix Format
$count++;
}
// Start Session For Array
session_start();
$_SESSION['instagram'] = serialize($instaArray);
header( 'Location: ../index.php' ) ;
} else {
// Check whether an error occurred
if (true === isset($_GET['error'])) {
echo 'An error occurred: '.$_GET['error_description'];
}
}
?>

Why not use an ID and then cookies rather than sessions + data (which are usually store on the server in text files in a temporary directory)? And keep all data within a database than allow the client to be accessible to the data. Sessions are also temporary.
Note, do you know if you have "globals" on?!
"Please note when working with sessions that a record of a session is not created until a variable has been registered using the session_register() function or by adding a new key to the $_SESSION superglobal array. This holds true regardless of if a session has been started using the session_start() function."
Reference:
http://www.php.net/manual/en/function.session-register.php

make session_start() first line after php
<?php
session_start();
and remove it from anywhere ele on page.
session_start() should be your first line in index.php also as in success.php
Note: The session_start() function must appear BEFORE the tag:
REF : http://www.w3schools.com/php/php_sessions.asp

I think you need to unserialize() your array in index.php.
$get_instagram = unserialize($_SESSION['instagram']);

Related

Yii loses session after OAuth redirect

I've lost a day and a half now trying to figure out why Yii is deleting all of the session data after I go to Twitter's OAuth page and back to my redirect.
Here is the main SiteController, where I go to Twitter. Here I am trying to save the oauth_token and token_secret values, so I can use them on the redirect controller.
function actionTwitter()
{
$consumerKey = "";
$consumerSecret = "";
$connection = new TwitterOAuth($consumerKey, $consumerSecret);
$request_token = $connection->oauth("oauth/request_token", array("oauth_callback" => "http://127.0.0.1/yii/?r=redirect&type=twitter"));
$oauth_token=$request_token['oauth_token'];
$token_secret=$request_token['oauth_token_secret'];
Yii::app()->session['token'] = $oauth_token; // This doesn't save!!
Yii::app()->session['token_secret'] = $token_secret; // This does not save!!
$url = $connection->url("oauth/authorize", array("oauth_token" => $oauth_token));
$this->redirect($url);
exit(); // some people have said I need to exit the session first after I redirect, but it doesn't help at all.
}
Here is my RedirectController, which is a separate controller and not in the main SiteController:
public function actionIndex()
{
$type = $_GET['type'];
if ($type == "twitter")
{
$token = Yii::app()->session['token'];
print($token);
}
}
I also have the session autostart set to true in my config file.
Thoughts on why it isn't working / stuff I have read about:
Twitter's site is HTTPS, and I am on localhost (which isn't HTTPS). For some reason that I forget this will make the session lose data when I redirect. If this is the case, how do I fix it without using HTTPS?
When I create new CHttpCookies they do not save either, I can't retrieve the value
I have tried Yii::app()->user->setState instead, which isn't working either.
I found the solution. It did not work because I was using 127.0.0.1 for the redirect, instead of the standard localhost. I changed that and all is working now.

File session: is it always generated?

Does Php always create a session file as soon as session_start() is called, even though there's nothing to keep track of (= no variable written in $_SESSION[])? If so, why?
Default PHP file-based sessions encode the session ID into the session file's filename. Since that's the only place the ID is kept normally, SOMETHING has to be kept to store the id. That means you'll get a file created, even if nothing is EVER written to $_SESSION.
In PHP-like pseudo code, basically this is occuring:
function session_start() {
if (isset($_COOKIE[ini_get('session.name')])) {
// session ID was sent from client, get it
$id = $_COOKIE[ini_get('session.name')];
} else {
// no session ID received, generate one
$id = generate_new_id();
setcookie(ini_get('session.name'), $id, ......);
}
$session_file = ini_get('session.save_path') . '/sess_' . $id;
if (file_exists($session_file)) {
// found a session file, load it
$raw_data = file_get_contents($session_file);
$_SESSION = unserialize($raw_data);
} else {
// brand new session, create file and initialize empty session
file_put_contents($session_file, serialize(array());
$_SESSION = array();
}
// lock the session file to prevent parallel overwrites.
flock($session_file);
}

Setting PHP session on index page for XSRF check

I have run in to the following problem regarding XSRF tokens.
Client: AngularJS
Server: PHP
When the index.php is hit, PHP generates an XSRF token and saves it in a session.
A cookie is set with same value.
AngularJS reads the cookie and stores the value.
On subsequent POSTS, the XSRF token is sent as a header, and the idea is to compare the stored session token to the sent header.
Everything seems fine, no problems whatsoever.
BUT: the issue is, that PHP cannot read the session registered in index.php, because technically there have been no page reloads! If I hit F5 and reloads everything , the session is read nicely.
How can I set the XSRF Session token on index.php and have it available for subsequent ajax requests from the client?? I'm pulling out my hair on this one... appreciate feedback.
UPDATE
After changing the session identifier name, everything suddenly worked!
In index.php:
// Create token and set session
session_start();
$token = hash('sha256', uniqid(mt_rand(), true));
$_SESSION['XSRF']=$token;
Later, also in index.php:
/* Give token to Angular client */
<script>
angular.module("app").constant("CSRF_TOKEN", '<?=$_SESSION['XSRF'];?>');
</script>
Note that I'm not using a cookie, instead I set a constant which is then made available to the .run method in Angular:
in Angular:
angular.module('app').run(['CSRF_TOKEN','$http',function(CSRF_TOKEN,$http) {
$http.defaults.headers.common['CSRF_TOKEN'] = CSRF_TOKEN;
All requests to the server are routed to one common php file. The file checks if the header is set, and compares the two tokens:
// Only POST requests are checked (I don't use PUT/DELETE)
if($_SERVER['REQUEST_METHOD']=="POST"){
session_start();
$headerToken = $_SERVER['HTTP_CSRF_TOKEN'];
$sessionToken = $_SESSION['XSRF'];
if($headerToken!=$sessionToken){
header('HTTP/1.0 401 Unauthorized');
exit;
}
}
This is what I'm doing in my PHP/AngularJS projects:
index.php
session_start();
if (!isset($_SESSION['XSRF-TOKEN'])) {
$uniqueValues = md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']); //add more/less/any "unique" values, see comments
$_SESSION['XSRF-TOKEN'] = sha1(uniqid(microtime() . $uniqueValues, true));
setcookie('XSRF-TOKEN', $_SESSION['XSRF-TOKEN']);
}
any script called by AngularJS $http:
(AngluarJS uses the value of the cookie XSRF-TOKEN and will send it in every request as X-XSRF-TOKEN custom header, so we need to compare this value to the value stored in the session.)
function verifyXSRF() {
/*
$headers = apache_request_headers();
$headerToken = "";
foreach ($headers as $header => $value) {
if ($header == "X-XSRF-TOKEN") {
$headerToken = $value;
break;
}
}
*/
//more efficient, see comments
$headerToken = $_SERVER['HTTP_X_XSRF_TOKEN'];
if ($headerToken != $_SESSION['XSRF-TOKEN']) return false;
return true;
}
session_start();
if (!verifyXSRF()) die("XSRF error");
Feedback welcome as I don't know exactly if this is enough XSRF protection.

In my PHP + Ajax code, why does $_SESSION disappear during execution?

I'm working on a simple Ajax exercise where I separate the query, the Ajax, and the url that Ajax calls. In short, I run a query in one page and attach the resulting array to $_SESSION, then I display some html and the Ajax code calls a third page to get the elements from the array one by one via a counter attached to the $_GET superglobal. The three files are linked by require_once().
When the page loads initially, all is as expected. The $_SESSION contains the entire array pulled from MySQL, and the $_GET is null.
Once I click on the button to execute the Ajax code, the $_GET value changes and receives the value of the counter, as expected.
However, $_SESSION ceases to exist. The var_dump now returns null and I get an error Notice: Undefined variable: _SESSION in C:\wamp\www\.....\ajax.php. I don't understand why that is.
Here is my code. First, index.php :
<?php
session_start();
$dbhost = "localhost";
$dbuser = "admin";
$dbpass = "XXXXXXX";
$dbname = "test";
mysql_connect($dbhost, $dbuser, $dbpass);
mysql_select_db($dbname) or die(mysql_error());
$query = "SELECT ae_name FROM ajax_example";
$qry_result = mysql_query($query) or die(mysql_error());
$result;
while($row = mysql_fetch_array($qry_result,MYSQL_ASSOC)){
$result[]=$row;
}
$_SESSION['array']=$result;
require_once ("viewUsers.php");
require_once ("ajax.php");
?>
Then the html and ajax code in viewUsers.php:
<html>
<body>
<script type="text/javascript">
<!--
function createRequest() {
try {
request = new XMLHttpRequest();
} catch (tryMS) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (otherMS) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = null;
}
}
}
return request;
}
var indx=0;
function calcIndex(){
return indx++;
}
function ajax(){
ajaxRequest = createRequest();
var index=calcIndex();
var url="ajax.php?index=" + index;
ajaxRequest.open("GET",url, true);
ajaxRequest.onreadystatechange = display;
ajaxRequest.send(null);
}
function display(){
if(ajaxRequest.readyState == 4){
var ajaxDisplay = document.getElementById('ajaxDiv');
ajaxDisplay.innerHTML = ajaxRequest.responseText;
}
}
//-->
</script>
<form name='myForm'>
<input type='button' onclick='ajax()' value='Show next name' />
</form>
<div id='ajaxDiv'>Your result will be displayed here</div>
</body>
</html>
And then the PHP that receives the array from $_SESSION and (should) return the next item based on the value of $_GET['index']. The file is ajax.php.
<?php
var_dump('Get value in ajax.php',$_GET); // The values are as expected
var_dump('Session value in ajax.php',$_SESSION); // This global cease to exist after I click the button
if(isset($_SESSION['array'])){
$array=$_SESSION['array'];
$cnt=count($array);
$index=null;
if(isset($_GET['index'])){
$index=$_GET['index'];
if($index>=$cnt){
$str="And that's it....";
}else{
$str="The next name is ".$array[$index]['ae_name'];
}
echo $str;
}
}
?>
The problem is that session in ajax.php is not started / resumed.
When you call index.php, it is:
index.php -> .. -> ajax.php (SESSION EXISTS (session_start() called in index.php))
then you request your ajax.php through ajax:
html -> ajax.php (SESSION DOESNT EXISTS (session_start() was not ever called as we dont come from index.php))
You just need to initialize / resume session in your ajax.php, but you have to check if its not already initialized from index.php. Put this chunk of code into your ajax.php file:
if(!session_id()) // check if we have session_start() called
session_start(); // if not, call it
ajax.php needs a session_start() at the beginning, otherwise, when you call it standalone via ajax, you won't have a session, hence no $_SESSION var.
From PHP DOC
session_start() creates a session or resumes the current one based on a session identifier passed via a GET or POST request, or passed via a cookie.
When session_start() is called or when a session auto starts, PHP will call the open and read session save handlers. These will either be a built-in save handler provided by default or by PHP extensions (such as SQLite or Memcached); or can be custom handler as defined by session_set_save_handler(). The read callback will retrieve any existing session data (stored in a special serialized format) and will be unserialized and used to automatically populate the $_SESSION superglobal when the read callback returns the saved session data back to PHP session handling.
Without calling session_start definitely $_SESSION would not be populated accordingly why advice is to always call session_start if you in your script if you are going to be using sessions .
Quick Few steps
Remove require_once ("ajax.php"); from index.php its not needed there
PHP CODE
$_SESSION['array']=$result;
require_once ("viewUsers.php");
require_once ("ajax.php"); //<------ remove this
Add session_start(); to ajax.php
From PHP DOC on mysql_query
Use of this extension is discouraged. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide and related FAQ for more information. Alternatives to this function include:mysqli_query()
PDO::query()
Your index.php should finally look like this
session_start();
// Put this in config file
$dbhost = "localhost";
$dbuser = "admin";
$dbpass = "XXXXXXX";
$dbname = "test";
$array = array();
//Start DB Connection
$mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname);
$query = "SELECT ae_name FROM ajax_example";
$result = $mysqli->query($query);
//Get Information
while ( $row = $result->fetch_assoc() ) {
$array[] = $row;
}
$result->free();
$mysqli->close();
// Add Info to session
$_SESSION['array'] = $array;
require_once ("viewUsers.php");
#JDelage,
Your question has a very simple solution - Just add session_start() at the top of the ajax.php file.
However, the major problem here is lack of organization in your code structure.
Session / Configurations are preloaded in most of the actions. And these are included in a file which is loaded in every call.
Your file ajax.php apparently seems to be an independent file, however is dependent upon index.php, meanwhile index.php depends on ajax.php (require_once).
So the best work around for your type of code is as follows.
bootstrap.php
<?php
// just to check to prevent overwriting of your configs / preloads.
if(!defined("INITIALIZED")){
session_start();
//.. some other basic settings if you require
define("INITIALIZED", 1);
}
?>
index.php
<?php
include_once "bootstrap.php";
// .. your code
require_once("viewUsers.php");
require_once("ajax.php");
ajax.php (Yes you need session_start() here, because when you make asynchronous request to this file, it acts as an independent request regardless of index.php. AJAX call is a client side asynchronous request, not a server side. )
<?php
include_once 'bootstrap.php';
// .. your code
viewUsers.php
// since your viewUsers.php file isn't an independent file and is included by index.php only, you can simply add this line at the top to prevent direct invocation of the file.
<?php
if(!defined("INITIALIZED")){die();}
PS:
There isn't an unique solution. An approach is what you have to decide. Your approach is an approach, which isn't any kind of approach. Rest is fine.
I hope I have answered your queries.
Regards,
You have a number of if conditions that are making it difficult for you to see errors. Add some echo statements at those locations to see what is happening in your program flow. It will be easier to troubleshoot. For example:
<?php
//session_start();
echo 'You sent ' . $_GET['index'] . '<br>'; //Ensure index value arriving
if(isset($_SESSION['array'])){
$array=$_SESSION['array'];
$cnt=count($array);
$index=null;
if(isset($_GET['index'])){
$index=$_GET['index'];
echo 'Got to here<br>'; //Another checkpoint - send something back
if($index>=$cnt){
$str="And that's it....";
}else{
$str="The next name is ".$array[$index]['ae_name'];
}
echo $str;
}else{
echo 'GET var "index" was not set<br>';
}
}else{
echo 'SESSION var "array" was not set<br>';
}
?>
Of course, you will remove those echo statements as you fix your code... They are only temporary, for debugging.
I faced similar issue. I found that in one of the ajax call I forgot to call session_start().
when I ensured that I session_start() is always called in all the php code that are called thru ajax, then this problem went away.
When using AJAX sometimes the session is not carried over. In your AJAX post/get include the sessionID. Then on the receiving end do something like:
$sid = ($_POST['sid']) ? $_POST['sid'] : ''; //Check for posted session ID
session_start($sid); //Start session using posted ID or start new session
*Old-school method, yes, but tried and true.

browser cookie. and other options for achieve the same effect

How would I create a cookie that would store the randomly added body class for one browser session or for one day. My intention would be to randomly give every user a body background image and then store that image so that it won't change every pagereload or when they go to page 2.
Site http://www.midnightlisteners.com/
i am using this jQuery plugIn: https://github.com/carhartl/jquery-cookie
but it does not work somehow
My jQuery code:
the code that I use:
if($.cookie('userBackground') === null) {
var classes = ['body-bg1','body-bg2', 'body-bg3', 'body-bg4'];
var randomnumber = Math.floor(Math.random()*classes.length);
var chosenClass = classes[randomnumber];
$('body').addClass(chosenClass );
$.cookie('userBackground', chosenClass, { expires: 7, path: '/' });
} else {
//todo verify cookie value is valid
$('body').addClass($.cookie('userBackground'));
}
Errors i am getting:
Uncaught ReferenceError: require is not defined
Uncaught TypeError: Object function (a,b){return new e.fn.init(a,b,h)} has no method 'cookie'
Are there other ways to do this? php? pure javascript?
UPDATE:
If you want to make it only last the length of the session then just use the session instead:
<?php
if(!isset($_SESSION['bgclass'])) {
// lets make our cookie!
$classes = array('body-bg1','body-bg2', 'body-bg3', 'body-bg4');
$classIndex = array_rand($classes);
$_SESSION['bgclass'] = $classes[$classIndex];
}
$bgclass = $_SESSION['bgclass'];
?>
This way after the session times out or the browser is closed the user will get a new bgclass value.
If you already have php running i would do it that way. Much better to handle this server side if you can. Its also a bit simpler:
<?php
if(!isset($_COOKIE['bgclass'])) {
// lets make our cookie!
$classes = array('body-bg1','body-bg2', 'body-bg3', 'body-bg4');
$expire = time()+(60*60*24); // expire 1 day form now
$classIndex = array_rand($classes);
$bgclass = $classes[$classIndex]; // had $class here as opposed to $classes
setcookie('bgclass', $bgclass, $expire);
} else {
$bgclass = $_COOKIE['bgclass'];
}
?>
<html>
<head></head>
<body class="<?php echo $bgclass ?>">
...
</body>
</html>
The key thing to remeber is that a cookie is essentially a response header so you have to do this before headers have been sent (ie. anything from php is output to the browser).

Categories