Users can log into secure pages but not revisit the same page - php

As part of this php login and redirect software I have a piece of code I need to add to the beginning of every page to be secured.
It lets a user on perfectly if they have valid user login information, but if they go to another 'secured' page and attempt to revisit the original page (or just copy and paste its address in a new tab to visit) it goes to a denied access screen.
Does this error occur because theres something wrong with the session cache headers or is it some deeper problem?
It currently looks like this:
<?php
session_start();
session_cache_limiter();
header("Expires: Sat, 01 Jan 2000 00:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: post-check=0, pre-check=0",false);
require('config.php');
require('functions.php');
//this is group name or username of the group or person that you wish to allow access to
// - please be advise that the Administrators Groups has access to all pages.
if (allow_access(Users) != "yes")
{
include ('/home/folder/public_html/members/no_access.php');
exit;
}
?>
I've tried changing the headers from other people's questions etc but it doesnt change the problem. I've also looked at any relevant links and made sure they are not broken etc.
The allow access function seems to be this:
function allow_access($group)
{
if ($_SESSION[group1] == "$group" || $_SESSION[group2] == "$group" || $_SESSION[group3] == "$group" ||
$_SESSION[group1] == "Administrators" || $_SESSION[group2] == "Administrators" || $_SESSION[group3] == "Administrators" ||
$_SESSION[user_name] == "$group")
{
$allowed = "yes";
}else{
$allowed = "no";
}
return $allowed;
}

You don't need:
session_cache_limiter();
header("Expires: Sat, 01 Jan 2000 00:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: post-check=0, pre-check=0",false);
And might be the stuff that's actually causing the problems.
You can improve this answer by telling us what:
allow_access
Is. And of course use booleans instead of textual yes or no.
Also what is Users ? Is it not a constant from what I see and it is not an object from what I see and it is not a variable...So what is that?

Related

PHP MySql fetch json no content

I have problem fetching my result from db and convert to json. In my API call, It gives me empty content(total blank) of returned body with status 200.
This is my code:
$weekAndYear = $year."/".$week; // incoming params as e.g "2016/19"
$stmt = $this->db->prepare("SELECT r.*, p.code FROM report r, product p WHERE "
. "r.pid=p.pid AND r.product=:productCode "
. "AND r.status='Published' AND r.pid=25 AND r.week=:weekAndYear");
$stmt->bindparam(":productCode", $productCode);
$stmt->bindparam(":weekAndYear", $weekAndYear);
$stmt->execute();
while($price=$stmt->fetch(PDO::FETCH_ASSOC)) {
//echo $price;
$arr_price[] = $price;
}
$data['priceReport'] = $arr_price;
//echo $weekAndYear;
$data['status'] = "OK";
return json_encode($data);
When I tested the query in my phpmyadmin mysql server and it works fine.
On my php side, different $weekAndYear params will have some working well and some are not. Anything wrong on array part?
My API response headers:
Cache-Control →no-store, no-cache, must-revalidate, post-check=0, pre-
check=0
Connection →Keep-Alive
Content-Length →0
Content-Type →application/json
Date →Thu, 05 May 2016 06:49:28 GMT
Expires →Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive →timeout=5, max=100
Pragma →no-cache
Server →Apache/2.4.18 (Unix) LibreSSL/2.2.6 PHP/5.5.31
X-Powered-By →PHP/5.5.31
I've been scratching my head for few days and now I just have few hairs left.
Please help. Thank you.
I'm assuming (maybe wrongly) that your code snippet isn't a function.
Change the last line from return to echo as follows:
echo json_encode($data);
Unless the first code snippet is a function, you need to use json_encode not a return statement.
What happens is that Fetch can fetch any type of content, even HTML. What PHP does is it generates content writes it to a file and sends it to the browser. When you generate HTML with PHP you do not return it, you echo it to the page.
The same thing happens with AJAX. You use PHP to write data to a file and serve it.
So replace this:
return json_encode($data);
with this:
echo json_encode($data);

Initial creating then deleting a cookie works, but can't recreate it afterwards

I need to create and delete cookies.
The issue is that I can create, then delete cookie, but after previously deleted cookie I am not able to create a new one. Why?
It works once more after I clear the cache of the browser.
Creating cookie and redirecting to test page:
<?php
$cookie_name = 'name';
$cookie_time = 2000000000;
$cookie_path = '/';
$cookie_value = uniqid();
setcookie($cookie_name, $cookie_value, $cookie_time, $cookie_path);
echo '<script> window.location.assign("test.php"); </script>';
?>
Deleting a cookie and redirecting to test page:
<?php
$cookie_name = 'name';
$cookie_path = '/';
setcookie($cookie_name, '', time() - 3600, $cookie_path);
echo '<script> window.location.assign("test.php"); </script>';
?>
The test page just has print_r($_COOKIE); in it.
What am I doing wrong here? Is the name of the cookie an issue? Is it browsers limitation?
I need to be able to create and delete the cookie whenever I need to.
I tried to avoid the cache by using this code:
<?php
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>
The problem may be the browser is caching the page request independently of what the server is telling it to do.
There is a simple trick to get around this. Adding a changing variable to the query string will make the page request unique each time. This will also force the browser to re-load the page even when cached.
For example, add the following to the address bar / page request:
?abc=123
And change the number value each time. Alternatively you can even use a timestamp like so:
?<timestamp>
This will force a standards compliant browser to fetch the page each time.

Prevent Form resubmission upon hitting back button

I have searched many posts here and elsewhere but can't seem to find a solution to my problem.
I have a page which displays database entries: database.php. These entries can be filtered with a form. When I filter them and only display the ones I am interested in I can click an entry (as a link) which takes me to that entries page (via php GET). When I am on that entries page (i.e., "view.php?id=1") and hit the back button (back to database.php), the filter form requires to confirm the form resubmission. Is there any way to prevent this?
here are some (simplified) code examples:
Database.php:
<form>
<select>
<option>1</option>
<option>2
<option>
</select>
<input type="submit" name="apply_filter" />
</form>
<?php
if ( isset( $_POST[ "apply_filter" ] ) ) { // display filtered entries
$filter = $_POST[ "filter" ];
$q = "Select * from table where col = '" . $filter . "'";
$r = mysql_query( $q );
} else { // display all entries
$q = "Select * from table";
$r = mysql_query( $q );
}
while ( $rec = mysql_fetch_assoc( $r ) ) {
echo "<a href='view.php?id=" . $rec[ "id" ] . "'>" . $rec[ "name" ] . "</a><br />"; // this is where the link to the view.php page is...
}
?>
Now as mentioned, if I click on the link, it takes me to "view.php?id=whatever". On that page, I just get the ID from the url to display that single entry:
view.php:
<?php
$id = $_GET[ "id" ];
$q = "Select * from table where id = '" . $id . "'";
$r = mysql_query( $q );
while ( ) {
// display entry
}
?>
If I now hit the back button, the form on database.php (the one used to filter the DB results) requires confirmation for resubmission. Not only is this very annoying, its also useless to me.
How can I fix this? I hope the code examples and explanation of my problem are sufficient. If not let me know and I'll try to specify.
I know this question is old, but having this issue myself, two lines I've discovered that works are:
header("Cache-Control: no cache");
session_cache_limiter("private_no_expire");
There are two ways I know of to do this. The simple way and the hard way.
Regardless of the way, when you are dealing with a state-based page (using $_SESSION), which you should be doing to keep your pages "live" and under your control, is prevent the caching of all pages like this:
<?php
//Set no caching
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>
The hard way involves generating an id and storing it somewhere on the page as a hidden input or a &_SESSION cookie. Then you store the same id on the server as a $_SESSION. If they don't match, a series of preprogrammed if else type statements cause nothing to happen with the page is resubmitted (which is what it tries to do when you click back).
The easy way is to simply redirect the user back to the form submission page if the form was submitted successfully, like so:
header('Location: http://www.mydomain.com/redirect.php');
I hope this helps!
One thing that might help is making your filter form use a GET method instead of POST.
Browsers usually prevent POST input from being automatically resubmitted, which is something they don't do when GET input is used. Also, this will let users link to your page using a filter.
header("Cache-Control: no cache");
session_cache_limiter("private_no_expire");
NOTE: After using the post data what you have submitted from the form then, these two lines should be used at the end of function.so, when we are back to the redirected page, it will not ask you to resubmit the page. This will work.
I used the answer at How do I detect if a user has got to a page using the back button? to detect whether or not the visit was triggered by a browser's back button click, and then if that was the case, I used JavaScript to reload the page. When the page is reloaded, my code already handles the corresponding validations to make sure that the form is never submitted twice. The important part in my case was forcing the page reload when the form was revisited after clicking the browser's back button. This is my code in the URL where I wanted to apply this validation:
<script type="text/javascript">
if (window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
location.reload();
}
</script>
An alternative solution that also works if/when the page is reloaded involves checking the post's originality using $_SESSION. In a nutshell, check for a unique or random string.
In the form, add an input element with a value set using rand() or microtime():
<input type="hidden" name="formToken" value="<?php echo microtime();?>"/>
And then wrap the PHP function to validate and parse the form data in an if block:
if(!isset($_SESSION['formToken']) || $_POST['formToken'] !== $_SESSION['formToken'])){
$_SESSION['formToken'] = $_POST['formToken'];
/*continue form processing */
}
The solution the works for me is
$(document).ready( function() {
//prevent form submit on refresh or resubmit with back button
if ( window.history.replaceState ) window.history.replaceState( null, null, window.location.href );
}
Its already mentioned above but again i will say it, if you have used session_start() in your code then you just need to add this line in your header file like:-
<?php
header("Cache-Control: no cache");
?>
but if you didnt have used yet the session_start() then you can add the line below in your header file like:-
<?php
header("Cache-Control: no cache");
session_cache_limiter("private_no_expire");
?>
The following worked for me when I add this code to the end of my script after the submission/redirection
unset($_POST);
exit();
So simple but it took way too long for me to figure it out.
You need to remove the request which POST data from browser history
history.replaceState("", "", "/the/result/page")
See this answer
Also you may follow the Post/Redirect/Get pattern.

html always fetch fresh page from link

I'm setting a cookie on one page and trying to unset on the next page, which I reach via a link. However, the cookie only gets unset when I refresh the second page, F5.
For testing, I have the link and some cookie setting on the first page like this:
<?php
include("connect-db.php");
$id = "newuser";
setcookie("user_id", $id, time() + 31536000);
if (isset($_COOKIE["user_id"]))
echo "Welcome " . $_COOKIE["user_id"] . "!<br>";
else
echo "Welcome guest!<br>";
?>
<br>
<a href='next.php'>Next</a>
On the next page I have this php code:
<?php
header("Cache-Control: no-cache, must-revalidate, max-age=0"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header('Pragma: no-cache');
setcookie("user_id", "", time()-(60*60*24), "/");
echo "<br /> Welcome " . $_COOKIE["user_id"] . "!<br>";
?>
How can I make sure the cookie is unset on the second page, or the page is fetched anew?
This depends on what you are trying to do. If you have a dependency on the cookie on the client, then you may want to unset it using the client (JavaScript). If the dependency is on the server, then it'd be tough to know what your problem is since you can just write the second part of the code to not depend on the cookie after you "unset" it.
I don't fully recommend this as it's an extra page load that's probably not necessary, but you could also force the sending of headers.
if (isset($_COOKIE['user_id'])) {
setcookie(/* your params */);
header('Refresh: ' . $_SERVER['REQUEST_URI']);
exit;
}
you can try using the following code in second page
setcookie("user_id", "");
I hope you can solve your problem.

Why isn't PHP responding to my $_GET variables?

I have the following code in index.php (simplified):
<?php
print_r($_GET);
if ($_GET['f'] == "activate") {
//do stuff
}
if ($_GET['f'] == "disable") {
//do stuff
}
?>
and further down the page, some HTML:
<tr>
<td style='font-size: 0.9em;'>email#address.ac.uk</td>
<td style='font-size: 0.75em;'><span style="color: #00AF28;">Active</span></td><td style='font-size: 0.75em;'>Disable</td>
</tr>
The two hyperlinks will point the browser to the URL index.php?f=disable&id=email#address.ac.uk and index.php?f=disable&id=email#address.ac.uk, respectively.
Upon clicking the hyperlink (and directing the browser to index.php?f=disable&id=email#address.ac.uk), the result of print_r($_GET) is:
Array ( [f] => disable [id] => email#address.ac.uk )
However, the 'if' statement:
if ($_GET['f'] == "disable") {
//do stuff
}
Does not execute until I refresh the page, or press the enter key on the address bar.
I'm using Chrome 16 on OSX for this, with PHP5.
Many thanks
Try to disable the cache. You can do this by sending some http headers to the browser. Here are an example from php.net
<?php
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
?>

Categories