PHP header() called via AJAX not working properly - php

I'm new to web development.
Right now I'm working on a login feature on a site. I used Javascript/AJAX to fetch the username and password and send it to a PHP file for verification on the MYSQL database. That's what I'm about to make.
My question is why can't the header() function working properly? I want after the user login she is redirected to the profile page (profile.php)
Here's snippet of the PHP (login.php):
$query = "SELECT * from user WHERE username = '$uname' AND password = md5('$pass');";
$ret = mysql_query($query) or die(mysql_error());
if(!$ret) {
$msg = "Invalid query " . mysql_error() . "\n";
$msg .= "Whole query " . $query;
die($msg);
}
$userid = -1;
while($row = mysql_fetch_array($ret)) {
$userid = $row["ID"];
}
$cnt = mysql_num_rows($ret);
if($cnt == 1) {
session_start();
$_SESSION["userid"] = $userid;
$_SESSION["uname"] = $uname;
echo "You have logged in successfully!";
header("Location: profile.php");
} else {
echo "Wrong Username/Password";
}
And here's for the Javascript (an AJAX function):
var obj;
var url = "login.php";
var params = "uname=" + document.getElementsByName("uname")[0].value + "&pass=" + document.getElementsByName("pass")[0].value;
if(window.XMLHttpRequest) { // Major browsers
obj = new XMLHttpRequest();
obj.open("POST",url,true);
obj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
obj.setRequestHeader("Content-length", params.length);
obj.setRequestHeader("Connection", "close");
obj.onreadystatechange = function() {
if(obj.readyState == 4) {
if(obj.status == 200) {
// success
} else {
alert("Problem in returned data" + "Error status=" + obj.status);
}
}
}
obj.send(params);

I don't think the redirect will work with AJAX. This is what will happen:
AJAX request is sent to login.php
login.php sends back a header with Location: profile.php
The browser then redirects and fetches profile.php
The results of profile.php is then passed to your XMLHttpRequest Object.
A way to get the AJAX response to redirect your page is to do this:
The response from login.php returns a JSON response containing the status code (302 or 301) and the location to redirect to.
The response itself has a status code of 200 (successful).
The process the JSON response and check the status code for 302 or 301 and redirect to the location.

You need to take out the echo statement before header(). Header won't work if anything has been output to the browser before it is called.
Here's the php doc on that.

What's happening exactly?
After header() is called in php, php still executes the rest of the script unless you stick an exit; after the header() call. This is only if you don't want to execute the rest of login.php

You can one thing replace your code header("Location: profile.php"); by echo "window.location.href='profile.php'; and replace your success function as
if(obj.status == 200) {
eval(obj.responseText);
}
Thats it. now a response will be evaluated by script and will redirect your page on profile.php

Related

Php Header redirects, but doesnt echo after that

It redirects them back to the homepage but I want it to also display a box.
if($m->send()){
header('Location:http://blankwebsite.com/');
echo '<script>
alert("Your Quote Request has been submitted!");
</script>';
}
else{
echo $m->ErrorInfo;
}`
You could save the html in a session variable, display it after redirect and empty the session variable like a flash message at script start up.
if($m->send()){
$_SESSION['redirectMessage'] = base64_encode(utf8_encode('<script>alert("Your Quote Request has been submitted!");</script>'));
header('Location:http://blankwebsite.com/');
}
else{
echo $m->ErrorInfo;
}
On new page request or redirect:
if isset($_SESSION['redirectMessage']) {
echo htmlentities(base64_decode($_SESSION['redirectMessage']), ENT_QUOTES, 'utf-8');
$_SESSION['redirectMessage'] = null;
}
This solution uses sessions, so do make sure session_start() is called at the top of the script.

How to Store session data of user

first question for the site(i am new to this site)
thought to post my most difficult problem .....
I have Login system in my site after successful login my protected page is displayed only after login i want to add $_SESSION['point'] to store the point of user.and save it to data base and the point will be increased if user click link. I want to store this increased point into my userdb.php. where all sign up information i kept.(i have not used MySql for signup Form I have used userdb.php file)my protected page php code are
<?php
if (session_id() == "")
{
session_start();
}
if (!isset($_SESSION['username']))
{
header('Location: #');
exit;
}
if (isset($_SESSION['expires_by']))
{
$expires_by = intval($_SESSION['expires_by']);
if (time() < $expires_by)
{
$_SESSION['expires_by'] = time() + intval($_SESSION['expires_timeout']);
}
else
{
unset($_SESSION['username']);
unset($_SESSION['expires_by']);
unset($_SESSION['expires_timeout']);
header('Location: #');
exit;
}
}
if (session_id() == "")
{
session_start();
}
if (session_id() == "")
{
session_start();
}
?>
My display.php to show urls
<?php
mysql_connect('Server', 'user', 'passs');
mysql_select_db('add');
$query =mysql_query('select * from addimage');
while( $row = mysql_fetch_assoc($query) )
{
echo '
<div style="min-width:300px;height:100px;border:red 5px;float:left;">'.$row['url']. '</div>';
}
?>
You can write your login PHP like,
<?php
// if PHP > 5.4: if (PHP_SESSION_NONE == session_status()) {
if ('' == session_id()) {
session_start();
}
if (isset($_SESSION['expires_by'])) {
$expires_by = intval($_SESSION['expires_by']);
if (time() < $expires_by) {
$_SESSION['expires_by'] = time() + intval($_SESSION['expires_timeout']);
} else {
session_destroy();
}
}
if (!isset($_SESSION['username'])) {
Header('Location: ' . $_SERVER['REQUEST_URI']);
exit();
}
?>
Then to click on the URLs you could perhaps use jQuery and AJAX. You should declare a class like "link-block" in your CSS, and write the URLs like this
echo '<div class="link-block">'.$row['url'].'</div>';
and add a click handler to those DIVs in the page's onReady Javascript, after including jQuery scripts:
$('.link-block').on('click', function(e) {
$.post('/increase-points.php', { }, function(retval){
if (retval.newpoints) {
$('#point-block').html(retval.newpoints);
}
});
});
The increase-point handler needs to open the session, which is the same code as you have above (so you can put it into an external include "session.php"), and open the database connection (another include...), then:
UPDATE usertable SET points = points + 1 WHERE user_id = {$_SESSION['user_id']};
or if you have a username only (ensure it's properly escaped)
...WHERE username = '{$escapedSessionUsername}';
By the way, I need to add the standard mysql_* deprecation disclaimer.
After which, you might return the current points to be displayed into a DIV with id of "points-block":
You have <span id="points-block"></span> points.
by returning it in JSON after querying them from the database (or you can keep them in session and update both DB and session; it saves you one query)
// This in /update-points.php
$retval = array('newpoints' => $updated_points);
Header('Content-Type: application/json;charset=utf8');
die(json_encode($retval));
You can do this in other ways too, but I saw no anchor in your link div, so I guess you want something dynamic, which mostly means AJAX.

Anti-CSRF not working correctly

<?php
$_SESSION['csrf_token'] = md5(uniqid(rand(), true));
?>
<?php
$csrf1 = $_POST['csrf_token'];
$csrf2 = $_SESSION['csrf_token'];
if($csrf1 === $csrf2) {
//not executing
} else {
}
?>
javascript
var csrf = "<?php echo $_SESSION['csrf_token']; ?>";
var ajax = ajaxObj("POST", "index.php");
ajax.onreadystatechange = function() {
if(ajaxReturn(ajax) == true) {
if(ajax.responseText != "success"){
} else {
window.location.replace("login.php");
}
}
}
ajax.send("csrf_token="+csrf);
}
return false;
So, here's some PHP from my code that generates a CSRF token, puts it in session, then checks whether the session value and the POST value are the same. The problem is, the if statement isn't executing. When I echo out the session token right before I send off the request using ajax, the session token is the same. I'm fairly sure that the session token is changing, and I am unsure why.
Edit: I added my javascript. I removed a lot from it, so I hope I didn't mess anything up on it.
A very important piece of information OP failed to provide is that the request goes to the same script that makes his token. Therefore, what is happening is exactly what is supposed to happen. Here is a solution I provided to him on a different website.
<?php
if((isset($_SESSION['csrf_token'], $_SESSION['time']) && time() - $_SESSION['time'] > 60) || !isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = md5(uniqid(rand(), true));
$_SESSION['time'] = time();
}
?>
if($csrf1 === $csrf2) {
change so: if($csrf1 == $csrf2) {
I would echo the contents and visually compare the two to check for identical values. For what it is worth, have you tried strcmp()?
if(strcmp($csfr1, $csfr2) == 0) {
//Got a match
} else {
//No match, look at the two strings for debug purposes.
print("<pre> CSRF1: $csrf1 \n CSRF2: $csrf2 </pre>");
}

php header not working after applying jQuery

// script.js
$(document).ready(function(){
$(".loginProzor").hide();
$(".login").click(function(){
$(".loginProzor").fadeToggle(300);
});
$("#prijavi").click(function(){
if($("#user").val() == "" || $("#pass").val() == ""){
$("#labelGreska").html("Unesite korisničke podatke");
}
else{
$.post($("#forma").attr("action"), $("#forma :input").serialize(),
function(data){
$("#labelGreska").html(data);
});}
$("#forma").submit(function(){
return false;
});
});
});
// form
<form id="forma" action="login.php" method="post">
<label>Korisničko ime</label><br>
<input type="text" name="user" id="user"><br>
<label>Lozinka</label><br>
<input type="password" name="pass" id="pass"><br>
<input type="submit" value="Prijavi se" id="prijavi">
<label id="labelGreska"></label>
</form>
//login.php
<?php
include 'funkcije.php';
include 'spojiBazu.php';
$user = $_POST['user'];
$pass = $_POST['pass'];
if(!$user){
$greske[] = 'Unesite korisničko ime';
}
$pass = md5($pass);
$ucitaj = mysql_query("select * from login where username = '$user' and password = '$pass'");
session_start();
if(mysql_num_rows($ucitaj) === 0){
echo 'Korisnički podaci nisu validni, molimo pokušajte ponovo.';
}else{
$korisnik = mysql_query("select username from login where username = '$user'");
$podatak = mysql_result($korisnik, 0);
$_SESSION['user'] = $podatak;
header("Location: index.php");
}
?>
Hello
I'm learning web development and I ran into a problem. I created simple login form. It evaluates some errors using jQuery and the rest of errors are evaluated using PHP. Everything works except Header command in PHP. When user succesfully logs in, header command should redirect to index.php so user can verify it is logged in, but in this case header tag don't work.
Before applying jQuery (all errors were handled by PHP) header command worked with no problems. Can you tell what's wrong here?
Details,
Since AJAX happens "behind the scenes" (so to speak) your redirect will just interrupt the response to your javascript handler. So PHP cannot redirect your browser now, jQuery can. So use jQuery to redirect the user.
You'll need to return the URL and have your callback kick the browser to a new location.
On this note, since you have to return data to the front end, you'll want to add a status or similar variable so that you can switch your front end behavior based on whether the call "failed" or not.
Exactly what Marc B pointed,
"You're doing the ajax call - the php header will redirect the ajax response... not the page that the user is currently sitting on. You will have to modify your javascript code in the client to change the location."
A javascript redirect is as simple as window.location.href = "http://mylocation";.
Solution to your problem,
JQUERY
// script.js
$(document).ready(function(){
$(".loginProzor").hide();
$(".login").click(function(){
$(".loginProzor").fadeToggle(300);
});
$("#prijavi").click(function(){
if($("#user").val() == "" || $("#pass").val() == ""){
$("#labelGreska").html("Unesite korisničke podatke");
}
else{
$.post($("#forma").attr("action"), $("#forma :input").serialize(),
function(data){
if(data=="success"){
window.location.href = "index.php";
} else{
alert("login failed");
}
});
}
$("#forma").submit(function(){
return false;
});
});
});
PHP
<?php
include 'funkcije.php';
include 'spojiBazu.php';
$user = $_POST['user'];
$pass = $_POST['pass'];
if(!$user){
$greske[] = 'Unesite korisničko ime';
}
$pass = md5($pass);
$ucitaj = mysql_query("select * from login where username = '$user' and password = '$pass'");
session_start();
if(mysql_num_rows($ucitaj) === 0){
echo 'failed';
exit;
}else{
$korisnik = mysql_query("select username from login where username = '$user'");
$podatak = mysql_result($korisnik, 0);
$_SESSION['user'] = $podatak;
echo "success";
}
?>
from http://www.php.net/manual/en/function.header.php
Remember that header() must be called before any actual output is
sent, either by normal HTML tags, blank lines in a file, or from PHP.
It is a very common error to read code with include, or require,
functions, or another file access function, and have spaces or empty
lines that are output before header() is called.
You can try with a javascript redirection or remake your source code with the header at the begining
header() will not work after output has been echoed to the screen.
Check funkcije.php and spojiBazu.php to see if any echo happening. If they are you need to find a way to remove the echos from those to included files before you call header() in login.php.

Clearing the cookie programmatically

I have a login page called signin.php where a user can enter an email and password. On clicking submit button, page directs to connection_validate.php. This page validates the user entered data with database. If it's a registered user, the page directs to calendar.php. If the entered data is incorrect, it should redirect to signin.php. If the entered data is incorrect, I have placed cookie like this:
//action to be done if e mail id and password matches with database records
if(mysql_num_rows($result)>0)
{
header('location:calendar.php');
}
//action to be done if e mail id and password does not matches with database records
else
{
setcookie('message','incorrect login data');
header('location:signin.php');
}
In signin.php, I have written the code for displaying an alert if login information is incorrect like this:
<?php
include("include/minfooter.php");
if(isset($_COOKIE["message"]))
{
if(!($_COOKIE["message"]==" "))
{
echo "<script>
alert('Incorrect login information');
</script>";
setcookie("message"," ",time()-3600);
}
}
?>
My issue is that alert is displaying each time when I load the signin page if I have entered a error login data once. If I press the back button from the calendar.php to signin.php also, alert starts showing. I understood that the problem is with cookie. Cookie has not been removed. How can I solve this issue?
Update your signin.php as follows
<?php
include("include/minfooter.php");
if (isset($_COOKIE["message"]))
{
echo "<script>
var delete_cookie = function(name) {
document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:01 GMT;';
};
var msg = '" . $_COOKIE["message"] . "';
if (msg != '')
alert('Incorrect login information');
delete_cookie('message');
</script>";
}
?>
If you are using a session you can use the $_SESSION variable instead of a cookie value. Also you can not use setcookie() AFTER you have output content since setcookie() will send an HTTP header which must be sent prior to any content being sent.
session_start();
//action to be done if email id and password matches with database records
if (mysql_num_rows($result) > 0)
{
header('Location: calendar.php');
exit;
}
//action to be done if email id and password does not matches with database records
else
{
$_SESSION['message'] = 'incorrect login data';
header('Location: signin.php');
exit;
}
Then:
<?php
session_start();
include("include/minfooter.php");
if (!empty($_SESSION['message']))
{
echo "<script>alert('" . $_SESSION["message"] . "');</script>";
$_SESSION['message'] = '';
}
?>
Ok maybe is better to use session for that use a index ['messages'] on the $_SESSION array, then cleanup, the cookie should be used when you want reference some info after the user get out of your page. I made your code on using cookies, but consider using session:
<?php include("include/minfooter.php");
if(isset($_COOKIE["message"]) && !empty($_COOKIE["message"])
{
echo "<script>
var msg = '<?php echo $_COOKIE["message"];?>';
if (msg != "")
alert('Incorrect login information');
</script>";
unset($_COOKIE["message"]);
}
?>

Categories