Setting a cookie in an AJAX request? - php

I'm validating a login form with jQuery AJAX call to PHP. In php, I create a session and if they checked the 'remember me' checkbox, I want to create a cookie. Here's the php code:
<?php
include '../includes/connection.php';
date_default_timezone_set('GMT');
$name = $_POST['username'];
$pass = $_POST['password'];
$query = mysql_query("SELECT id, username, password FROM users WHERE username = '$name' LIMIT 1");
if(mysql_num_rows($query) == 0) {
echo 'error';
exit;
}
while($row = mysql_fetch_array($query)) {
if($row['username'] == $name && $row['password'] == $pass) {
session_start();
$_SESSION['username'] = $row['username'];
$_SESSION['usrID'] = $row['id'];
echo 'success';
if($_POST['remember']) {
setcookie('username', $row['username'], $exp);
setcookie('password', $row['password'], $exp);
setcookie('usrID', $row['id'], $exp);
}
} else {
echo 'error';
exit;
}
}
?>
The session is set successfully, however the cookie is not set at all. I've tried setting all the values (domain, path, etc.) but that didn't change anything. Is there anything obvious I'm missing?

Here are few suggestions:
Make sure that you are specifying the correct expiration format of date
When setting a cookie on a page that redirects, the cookie must be set after the call to header('Location: ....'); eg:
header('Location: http://www.example.com/');
setcookie('asite', $site, time()+60*60, '/', 'site.com');
If you have human urls like www.domain.com/path1/path2/, then you must set cookie path to / to work for all paths, not just current one.
setcookie('type_id', $new_type_id, time() + 60*60*24*30, '/');
Notice the last / in the arguments.
From PHP manual:
The path on the server in which the
cookie will be available on. If set to
'/', the cookie will be available
within the entire domain . If set to
'/foo/', the cookie will only be
available within the /foo/ directory
and all sub-directories such as
/foo/bar/ of domain . The default
value is the current directory that
the cookie is being set in.
setcookie() defines a cookie to be sent along with the rest of the HTTP headers. Like other headers, cookies must be sent before any output from your script meaning there should be no html/code echo statements before that.

You won't be able to set the cookie server-side when using an AJAX call. Instead, wait until you get a successful response and set the cookie client side. To make it easier, you could use a jQuery plugin.

Related

Detecting a cookie set using setcookie without a page reload

I am maintaining the code for an eCommerce website, they use a highly modified version of osCommerce v2.2 RC2. Was noticing an issue where the session isn't started for a new user until they visit the 2nd page of the site.
Looking at the code, before starting the session, it tries to set a cookie. If it detects the cookie it starts the session. Something along this line:
setcookie('cookie_test', 'please_accept_for_session', time()+60*60*24*30, $cookie_path, $cookie_domain);
if (isset($_COOKIE['cookie_test'])) {
session_start();
...
I found an article here that talks about a situation like this, it states:
The first time you only tell the browser to set the cookie, at the time, there is no cookie data in the request header (which could get from $_COOKIE).
Which explains why it takes two page loads for the session to be started. One to set the cookie and one to get notification from the browser that the cookie is set.
My question is, is there anyway around having to go through two page loads to detect the cookie was successfully set on the users browser?
I found this question that didn't really answer my question completely. The highest voted solution was:
setcookie('uname', $uname, time()+60*30);
$_COOKIE['uname'] = $uname;
Which may make it "work" but it doesn't truely tell me that the script was able to set a cookie successfully.
I also found this question, that suggested accessing the headers_list to find the cookie information like so:
function getcookie($name) {
$cookies = [];
$headers = headers_list();
// see http://tools.ietf.org/html/rfc6265#section-4.1.1
foreach($headers as $header) {
if (strpos($header, 'Set-Cookie: ') === 0) {
$value = str_replace('&', urlencode('&'), substr($header, 12));
parse_str(current(explode(';', $value, 1)), $pair);
$cookies = array_merge_recursive($cookies, $pair);
}
}
return $cookies[$name];
}
// [...]
setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . getcookie('uname');
Which, again, doesn't seem to be verifying that the cookie was set successfully. All this appears to do is search the headers being sent to the browser for the cookie value.
The only solution I can think of is to redirect on the first visit after setting the cookie. Is there any other way?
Here is the answer:
<?php
function set_cookie($name, $value) {
if (!isset($_COOKIE[$name]) || ($_COOKIE[$name] != $value)) {
$_COOKIE[$name] = $value;
}
setcookie($name, $value, strtotime('+1 week'), '/');
}
// Usage:
set_cookie('username', 'ABC'); //Modify the value to see the change
echo $_COOKIE['username'];

PHP: Remember Me, Stay logged in doesn't work

In my PHP project, I want to add a user remember me checkbox so that everybody can choose to stay logged in:
Until now I do my normal log in like:
public function loginUser($psMail, $psPwd, $pnRememberMe = 0) {
// Check credentials and so on
// If mail and password matches
if(CREDENTIALS OKAY) {
$_SESSION["username"] = "foo";
$lnExpire = time() + 3600 * 24 * 60;
setcookie("remember", base64_encode(USERID), $lnExpire);
setcookie("rememberToken", md5(SOMESTUFF), $lnExpire);
}
}
When I log in, I can see the created cookie variables with:
print_r($_COOKIE);
Now I try to leave the site with my logout function:
// Unset the session variables
$_SESSION = array();
// Destroy the session.
session_destroy();
But now, when I am at the landing page, there are also my cookies gone?
Could this be because of my session site settings?
ini_set("session.use_only_cookies", "1");
ini_set("session.use_trans_sid", "0");
php function setcookie has fourth argument path, from documentation "The path on the server in which the cookie will be available on". By default it set path to actual your directory. Try set "/" Then it will be available for all domain. http://php.net/manual/en/function.setcookie.php
Try this code hope it will work for you
if(count($_POST>0) && isset($_POST['checkbox']))
{
setcookie('name',$_POST['uname'],time()+3600);
setcookie('password',$_POST['pw'],time()+3600);
}
elseif(count($_POST)>0)
{
setcookie('name','',time()-3600);
setcookie('password','',time()-3600);
}
if(count($_POST)>0 && $_POST['uname']!="" && $_POST['password']!="")
{
if(isset($_COOKIE['name']) && isset($_COOKIE['password']))
{
echo $_COOKIE['name'];
echo $_COOKIE['password'];
}
your login detail code here.....

Issue with cookies / expiring session

I have users who write articles and when they leave there computer for a while and come back then submit a post the author / user_id is recorded as a NULL value. I'm assuming the session is expiring. I have:
ob_start();
session_start();
if(isset($_SESSION['user_id'])) {
$ext = time() + 31560000;
setcookie('name', $_SESSION['user_id'], $ext);
}
On the top of the index page where a user is redirected upon login.
Also, this is what happens when they actually log in:
$user_id = get_user_id($some_variable); // get's the user_id
$username = get_username($some_variable); // get's username
$_SESSION['user_id'] = $user_id;
?>
<script type="text/javascript">
window.location = 'http://site.com/<?php echo $username; ?>';
</script>
<?php
exit();
Is this properly configured, and why would the user's sessions be expiring? They're not exiting the browser, it's just inactivity. What would be causing this?
I don't know what you try to achieve with
if(isset($_SESSION['user_id'])) {
$ext = time() + 31560000;
setcookie('name', $_SESSION['user_id'], $ext);
}
But that do not increase the php session lifetime, but only create a cookie called name that have the $_SESSIOn['user_id'] as value and expire 31560000 seconds after creation.
If you want to change your session lifetime see session.configuration

PHP header(Location: ...): Force URL change in address bar

I'm currently working on a mobile site with authentication using PHP sessions with a database.
I have a login page with a form that goes to server_login.php on submit. The php file then creates some session data (store in $_SESSION), and redirects the user back to the index page:
header("location:../../index.php");
The new web page (index.php) loads correctly; however, when the header redirects the page, the URL at the address bar is not changed; it stays at *http://localhost/php/server/server_login.php* instead of http://localhost/index.php and thus all my other resources that makes use of relative pathing could not be loaded. It's as if the web page still thinks that it resides at /php/server instead of /.
Strangely, my other use of header("location: ...") at logout.php works and redirects the page successfully with a URL change.
I've made sure that there are no outputs in my *server_login.php* before the header redirect (above it are just mysql calls to check) and I've used ob_start() and ob_end_flush() too.
Are there any methods of forcing the URL on the address bar to change (and thus hopefully fix the relative path problem)? Or am I doing something wrong?
P/S: I am using jQuery Mobile.
EDIT: Here's my code for the redirection that doesn't change the URL:
// some other stuff not shown
$sql = "SELECT * FROM $user_table WHERE email = '$myemail' AND password = '$mypassword'";
$login_result = mysql_query($sql, $connection);
$count = mysql_num_rows($login_result);
if ($count == 1) {
// Successfully verified login information
session_start();
if (!isset($_SESSION['is_logged_in'])) {
$_SESSION['is_logged_in'] = 1;
}
if (!isset($_SESSION['email'])) {
$_SESSION['email'] = $myemail;
}
if (!isset($_SESSION['password'])) {
$_SESSION['password'] = $mypassword;
}
// Register user's name and ID
if ((!isset($_SESSION['name'])) && (!isset($_SESSION['user_id']))) {
$row = mysql_fetch_assoc($login_result);
$_SESSION['name'] = $row['name'];
$_SESSION['user_id'] = $row['user_id'];
}
header("Location: http://localhost:8080/meet2eat/index.php");
} else {
// Not logged in. Redirect back to login page
header("Location: http://localhost:8080/meet2eat/php/login.php?err=1");
}
Try changing:
header("Location : blabla")
^
|
(whitespace)
To
header("Location: blabla")
Well, if the server sends a correct redirection header, the browser redirects and therefore "changes the url". It might be a browser issue, then.
I don't know if it has anything to do with it, but you should not send a relative url in the location header ("HTTP/1.1 requires an absolute URI as argument to ยป Location: including the scheme, hostname and absolute path, but some clients accept relative URIs. ", http://php.net/manual/en/function.header.php), and "location" must be capitalized, like:
header('Location: http://myhost.com/mypage.php');
In your form element add data-ajax="false". I had the same problem using jquery mobile.
Do not use any white space. I had the same issue. Then I removed white space like:
header("location:index.php"); or header('location:index.php');
Then it worked.
you may want to put a break; after your location:
header("HTTP/1.1 301 Moved Permanently");
header('Location: '. $YourArrayName["YourURL"] );
break;
I had the same problem with posting a form. What I did was that turning off the data-ajax.
Are you sure the page you are redirecting too doesn't have a redirection within that if no session data is found? That could be your problem
Also yes always add whitespace like #Peter O suggested.
I got a solution for you, Why dont you rather use Explode if your url is something like
Url-> website.com/test/blog.php
$StringExplo=explode("/",$_SERVER['REQUEST_URI']);
$HeadTo=$StringExplo[0]."/Index.php";
Header("Location: ".$HeadTo);
Just change home to your liking
$home_url = 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/home';
header('Location: ' . $home_url);
// Register user's name and ID
if ((!isset($_SESSION['name'])) && (!isset($_SESSION['user_id']))) {
$row = mysql_fetch_assoc($login_result);
$_SESSION['name'] = $row['name'];
$_SESSION['user_id'] = $row['user_id'];
}
header("Location: http://localhost:8080/meet2eat/index.php");
change to
// Register user's name and ID
if ((!isset($_SESSION['name'])) && (!isset($_SESSION['user_id']))) {
$row = mysql_fetch_assoc($login_result);
$_SESSION['name'] = $row['name'];
$_SESSION['user_id'] = $row['user_id'];
header("Location: http://localhost:8080/meet2eat/index.php");
}
As "cfphpflex" suggested you can add break; after setting the header. You can also echo something, such as echo 'test';.
Add exit at the end of header then it will work
header("location:index.php"); or header('location:index.php'); exit;
You are suppose to use it like header(Location:../index.php) if it in another folder
use
header("Location: index.php"); //this work in my site
read more on header() at php documentation.
why all of this location url?
http://localhost:8080/meet2eat/index.php
you can just use
index.php
if the php files are in the same folder and this is better because if you want to host the files
or change the port you will have no problem reaching this URL.

PHP authentication with multiple domains and subdomains

I have one main domain: main.com, subdomains: test1.main.com, test2.main.com and other domains one.com, two.com.
Now it's done like these:
ini_set("session.cookie_domain", ".main.com");
$domain = 'main.com';
login.php
$user = $db->query("SELECT id, login FROM users WHERE email=? AND password=?",
array($email, $password), "rowassoc");
if($user)
{
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_name'] = $user['login'];
$time = 100000;
setcookie('email', $email, time() + $time, "/", "." . $domain);
setcookie('password', $password, time() + $time, "/", "." . $domain);
header('Location: http://' . $user['login'] . "." . $domain);
exit;
}
added on each page:
if(!isset($_SESSION['user_id']))
{
if(isset($_COOKIE['email']) && isset($_COOKIE['password']))
{
$email = $_COOKIE['email'];
$password = $_COOKIE['password'];
$user = $db->query("SELECT id, login FROM users WHERE email=? AND password=?",
array($email, $password), "rowassoc");
if($user)
{
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_name'] = $user['login'];
}
}
}
else
{
$user = $db->query("SELECT id, login FROM users WHERE id=?",
array($_SESSION['user_id']), "rowassoc");
if(!$user)
{
setcookie('email', '', time() , "/", "." . $domain);
setcookie('password', '', time() , "/", "." . $domain);
unset($_SESSION['user_id']);
session_destroy();
setcookie("PHPSESSID","",time(), "/", "." . $domain);
}
else
{
$_SESSION['user_id'] = $user['id'];
$_SESSION['user_name'] = $user['login'];
}
}
logout.php
if(isset($_SESSION['user_id']))
{
setcookie('email', '', time() , "/", "." . $domain);
setcookie('password', '', time() , "/", "." . $domain);
unset($_SESSION['user_id']);
unset($_SESSION['user_name']);
session_destroy();
setcookie("PHPSESSID","",time(), "/", "." . $domain);
header('Location: /main');
exit;
}
But it works only on domain main.com and its subdomains test1.main.com, test2.main.com.
I need to somehow save the session and on other domains one.com, two.com.
How best to do safe authentication, if there are solutions, i really confused, please tell with example.
As far as I know, crossing sessions between sub-domains is fine, but it won't carry over to a whole new domain. To do that you need some sort of centralized data method, or an API.
Database method: you will have to create a remote MySQL data access so that domain2.com can access the database on domain1.com. When a log-in is performed, not only should it create a new session, but a unique log-in token (with an expiry time) should be put into the mysql database. Now, for every link that goes from domain1.com to domain2.com, you should add a $_GET variable that contains a randomly generated session id (md5 hash will do). domain2.com, upon receiving the visitor, will take the $_GET variable, run it through the MySQL database to find the login token, and if there is a match, consider that user to be logged on (and perhaps embed a $_COOKIE as well to store the login data). This will make the log-in transferrable between two completely different domains.
API method: you need to create an API method, so that domain1.com can respond to an external request from authorized domains to retrieve the login token upon a user being forwarded. This method will also require that all links going from domain1.com to domain2.com to be appended with a $_GET variable to pass the unique session hash. Then upon receiving the visitor, domain2.com will do a curl() request to domain1.com/userapi.php (or whatever you call the file) and the variables should be tested against what's in the database.
This is the best I can explain it.. to write this out in code is a significant piece of work so I cannot commit. But judging by your code, you have a very good understanding of PHP so I'm confident you will pull this off!
Good luck mate.
To keep your sessions going across multiple domains, you need to use session_set_cookie_params(). With that, you can specify your domain. For example...
session_set_cookie_params(10000, "/", ".main.com");
That will set the session timeout at 10,000 seconds for all documents under the site root, and for all subdomains of main.com.
You should call session_set_cookie_params() before you do session_start().
But if user reach domains one.com directly, than one.com can't know if user had login by the right answer mentioned above, seems like must use some extra js, it's jsonP! we let account.main.com/userLoginStat.php?callback=loginThisDomain to check if user had login main.com, if so, the js callback function loginThisDomain do some thing to autologin user to one.com.

Categories