I have the following PHP script within a file named login.php
<?php
$ref = $_SERVER['HTTP_REFERER'];
if ($ref == 'http://example.com/dir/invalid.php' || $ref == 'http://www.example.com /dir/invalid.php') {
echo '
<div id="invalid">
TESTTESTTESTTESTTESTTESTTESTTEST
</div>
';
}
?>
I have deliberately went to the invalid.php page (which redirects using header() to login.php) and this div does not show up. Does it have something to do with the referrer not really being invalid.php or is there an issue with the script?
Thanks
I don't think the HTTP_REFERER is what you think it is. Namely, it is the page from which the user followed a link to the current page. However, it's very unreliable as we rely on the browser of the user to correctly report this value.
I would suggest the option I thought you needed, except that the only one I can think of you might doesn't really makes sense... (checking if the url matches a url that's not the current script)... so I do not see what you are trying to do.
As promised several ways to do what you want to achieve:
First off, I don't like this solution at all and really consider it ugly, but it's the one closest to what you where trying to do.
invalid.php
require 'login.php'; // we include the file instead of referring to it
login.php
if ($_SERVER['SCRIPT_NAME'] == 'invalid.php')
{
// do whatever
}
The main difference between what you did and what I did for the user will be that here the url bar will show that you're at invalid.php and not somewhere else. This also means that refreshing doesn't make the message go away.
A better solution in my opinion is the following:
In your script that logs a user in (checks the database and everything):
if (!valid_login()) // pseudo-code, obviously
{
$_SESSION['invalid_login'] = true;
header('Location: login.php');
// previously, we had something like this instead of the two lines above:
// header('Location: invalid.php');
}
in login.php
if (isset($_SESSION['invalid_login']) && $_SESSION['invalid_login'])
{
$_SESSION['invalid_login'] = false;
// do whatever
}
Of course, this should be done with proper session facilities like starting up the session in both those files. Instead of using session variables, you could include the file and use normal variables or send GET variables through the header request, but both those solutions share a problem: refreshing doesn't make the message disappear. However, if you were to move the code from the top file of the two above to login.php (if it's not already there, I don't know what file that actually is...) you could once again use normal variables instead of session variables and have a solution in which refreshing does make it go away. In this case, you might argue that you are cluttering your files with bussiness logic and presentation, but there are solutions to that (like keeping it in a separate file, and including it into login.php, moving the html to another file and including that one into login.php or both.
Related
I have a framework and I think I'm following something like the MVC pattern: A framework (the model) an index page that controls the input (the controller) and the views pages (that are included inside main.php/the main html)
I read a lot about structure and logics, to write a good application. I read many comments like "Why are you outputting anything if all you are going to do is try and redirect the user to another page?". Well the answer is, the most common case: redirect after the user successfully logged in. Do I need to print something? Of course, the whole main page with a login form/post. How I'm supposed to do that redirection??
So I'm a bit confused about logics and structure of the application. How do you store all the output and do the header redirection without printing anything?
I was thinking about using javascript to do the redirection but I also read comments saying; "if you write good code (following a good logic/structre), you won't need to use hacks like javascript redirection". How is that even possible?
Because the php output_buffering should not be enabled.
I have the output_buffering enabled, and I can use header (after output) without any problem. If I use the javascript redirection the whole page reloads, but using header it just loads the content (the views content that are included in main.php).
So how do you do this without output_buffering?
If you want to redirect to a success page AND pass messages - say, after a successful login - an easy solution is to use "flash" sessions, where you store a message in a SESSION and then, as soon as it's used, you discard it. You don't need to sore anything in the output buffer for this.
This is a very basic example, but should give you the gist of it.
login.php
if($login_successful) {
// put your message in the session
$_SESSION['message'] = 'Login Successful';
// redirect to the success page
header('location: success.php');
}
success.php
<?php
session_start();
// check if $_SESSION['message'] exists
if(isset($_SESSION['message'])) {
// print the message
echo $_SESSION['message'];
// clear the session
$_SESSION['message'] = null;
}
Looks like you are mixing up some things here. What you are talking about are actually two different requests. Either the user wants to view the main page, or he wants to log in using that form on your main page. In your index.php you would have something like this (pseudocode):
if (isLoginRequest) {
// user wants to log in
if( validateLogin($loginFormData) ) {
redirect('successful');
} else {
displayLoginError();
}
} else {
// user wants to view main page
echo main.html
}
Update to answer the question in the comments: The better alternative would be to leave your form validation stuff in login.php and refer to that in your login form <form action="login.php" .... Then in your login.php you would have something like this:
if (loginSuccessful) {
redirect('success.php');
// no need to call die() or whatever
} else {
setFlashMessage('Login failed'); // set a flash message like timgavin described
redirect('index.php')
// also no die() or whatever
}
index.php then is responsible to display your main page and, if set, rendering the flash message from a failed login attempt.
Simple solution: Move the login post script from login.php to another file (login_post.php). The same for other scripts using header() after dom output. (no need to change the form action="")
In index.php:
$url = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
//some more security checks like esc_url() (non-php function)
if ($url == '/login') {
include('header_pages/login_post.php');
}
// all these includes before including main.php
// where views pages are included and the DOM output starts
Since header() is inside the post script, no more headers already sent errors (And output_buffering off, of course).
Same for logout page that is currently being included inside main.php
Thanks to the other answers, they helped me finding this solution.
im trying to finish my site and ensuring that the user cannot see anything that might help them in malicious ways or give them a bad experience on the site.
So for my pages where e.g login.php i check the request method, if its post continue if not then 404 etc.
However i have a couple of pages that gather some information from the database and i include them in the page. Some of them are quite large / complex so i prefer doing this to keep things tidier.
How can i go about redirecting the user to a 404 if they directly access these pages instead of them just being included?
Thanks. Hope you know what i mean! :)
<?php // top file, eg login.php
define('IN_SCRIPT', true);
include('infopage.php');
?>
<?php // included file, eg infopage.php
if (! defined('IN_SCRIPT')) {
// log message, throw header, etc.
// this is a direct access
exit(0);
}
// do whatever
?>
Alternatively, consider moving your info pages out of the web visible space.
I think that you can use some simple tricks.
where you want to include files, instead of simply
include('db.php')
do:
$including = 'yes';
include('db.php');
and in first lines of db.php:
if (!isset($including)) {
//show 404
exit;
}
//db job
so it does it's job if included, and shows a 404 if it is called directly.
Alternatively:
the first trick (and DEFINE) may be safer but if you don't want to change every file that includes the file;
just in db.php:
if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME'])) {
//show 404
exit;
}
//db job
I'm trying to get three things into a hidden form field in a Wordpress page:
The last "offsite" page visited before someone visited any page on my site (e.g., quite possibly a Google page)
The first page they visited on my site
The last page on my site before they went to the form page
The third one is easy (just use ), but the first two are giving me problems.
I'm trying to save #1 and #2 by using session variables, so that on every page, in the header, I have the following code:
<?php
session_start();
if (! isset($_SESSION['offsite_referer'])) {
$_SESSION['offsite_referer'] = $_SERVER['HTTP_REFERER'];
}
if (! isset($_SESSION['first_page'])) {
$_SESSION['first_page'] = $_SERVER['REQUEST_URI'];
}
?>
Then further down I have, as test code (to be changed to input type=hidden etc. later):
<p>offsite_referer: <?= $_SESSION['offsite_referer'] ?></p>
<p>first_page: <?= $_SESSION['first_page'] ?></p>
(FWIW, I also have session_start() at the top of my wp-config.php. Yes, my site has register_globals turned off.)
For some reason, $_SESSION['offsite_referer'] always ends up as my home page, even when I hit the form page (/free-reports) directly via link from another site. Similarly, first_page always shows up as /
Yes, I'm clearing all my cookies etc. between attempts, to force a new session to be created.
This code used to work fine on my pre-Wordpress site, so I can only think it has something to do with WP, specifically perhaps WP's redirection (WP's mod_rewrite stuff in .htaccess)
I tried changing $_SESSION['offsite_referer'] = $_SERVER['HTTP_REFERER'] to wp_get_original_referer() but it seemed to have no effect.
Incidentally, if I access my form page (at /free-reports/) as the first page on my site (after clearing cookies etc.) and printing $_SERVER['HTTP_REFERER'], it correctly shows the last offsite page - even though $_SESSION['offsite_referer'] doesn't.
I'm pretty perplexed, and have spent a fair amount of time trying to figure it out on my own, so any help to solve this would be appreciated.
Chances are, you can't really get the referer URL since some browsers don't send that and some people disable that, but here's how you could do that and I'll give you some extra tips here:
//first of all, initialize the session
session_start();
//Now call logvisit() to log where the user is coming from
logvisit();
function logvisit() {
$_SESSION['offsite_referer'] = $_SERVER['HTTP_REFERER']);
$browser = $_SERVER['HTTP_USER_AGENT']; //Gets the browser the user is using
//If you want to test it (disable the code below if you don't want to print that information):
echo "Offsite referer: $_SESSION['offsite_referer']<br>";
echo "Browser: $browser<br>";
}
Then to destroy the session you can use unset($_SESSION['offsite_referer']);
This is how I usually do it, and it's often a tidy way to do it.
I believe scunliffe had the key to this, as I was using IE to do the testing.
It works fine now, which I attribute to actually closing and restarting IE (apparently just deleting cookies doesn't do it, as you'd think, even though that works fine in Firefox).
I also changed what I was doing slightly to just save the full in-site browse history in a session variable, rather than only first and last page on the site.
The code I ended up with was the following, which is just at the top of my theme's header.php file:
<?php
session_start();
if (! isset($_SESSION['site_history'])) {
$_SESSION['offsite_referer'] = $_SERVER['HTTP_REFERER'];
$_SESSION['site_history'] = '';
}
$_SESSION['site_history'] .= ($_SERVER['REQUEST_URI'] . ';');
?>
I originally had session_start() also in wp-config.php when I was trying to figure this out, but was able to remove it (leaving just the above code in header.php) and things still work fine.
In case anyone finds this page wanting to do something similar, I was able to access this info in my WP page by adding the following to my theme's functions.php:
function get_offsite_referer() { return $_SESSION['offsite_referer']; }
add_shortcode('offsite-referer', 'get_offsite_referer');
function get_site_history() { return $_SESSION['site_history']; }
add_shortcode('site-history', 'get_site_history');
and then to pass the info on my Wordpress page/form:
<input type="hidden" name="offsite_referer" value="[offsite-referer]" />
<input type="hidden" name="site_history" value="[site-history]" />
scunliffe, if you'd posted your comment as a "reply" I would have "accepted" it, since it was what most closely led me in the right direction, but as a comment I could only upvote it so that's what I did. Thanks!
I am trying to hide my websites cms application...
So i thought i would add a bit of php to any random page on my site, that includes a GET referance to some random string... So basically, if you go to x page, and add ?RANDOMSTRING the cms index is included. This is stored above the web root... Here is the peice of php:
if (isset($_GET['J7sd-H3sc9-As3R']))
{
require_once($docRoot . '/../../includes/admin/index.php');
}
Basically, index.php is laid out as a page with 3 fieldsets. In the 3 field sets are various links relating to various applications that deal with various tasks. They were accessed through the same means as the above code. And they were held in the web root and were able to be accessed via http...
That all worked perfectly fine, But the problem now comes when i try to access any specific part of the cms...so what would have been:
http://www.mysite.com/admin/part/
is now:
include($_SERVER['DOCUMENT_ROOT'] . '/../../includes/admin/part/index.php');
Or something of the sort...
So now when i go to my page at
http://www.mysite.com/randomDirectory/
and add:
http://www.mysite.com/randomDirectory/?J7sd-H3sc9-As3R
I get sent to my cms... Cool... But when i try to click on any section i get this header:
http://www.mysite.com/randomDirectory/?part
and the page gets refreshed to:
http://www.mysite.com/randomDirectory/
If that makes sense...
Could any provide me with any input or suggestions regarding the task that i am trying to accomplish? I am not sure if it is even possible to start off with, but it seems simple enough.
Any replies would be greatly appreciated, Thanks!
I guess you should append at the end of every link in your page something like
<?php if (isset($_GET['J7sd-H3sc9-As3R'])) echo '?J7sd-H3sc9-As3R'; ?>
Example:
http://www.mysite.com/randomDirectory/randomPage<?php if (isset($_GET['J7sd-H3sc9-As3R'])) echo '?J7sd-H3sc9-As3R'; ?>
edit
An easier way to do this would be to use sessions, in this way:
<?php
session_start();
if (isset($_GET['J7sd-H3sc9-As3R']))
{
$_SESSION['token'] = 'J7sd-H3sc9-As3R';
}
if (!isset($_SESSION['token']) || $_SESSION['token'] !== 'J7sd-H3sc9-As3R')
{
exit;
}
// go on with your page
?>
In this way, when you open a page with your token in the url, the session is started and the token is saved in the session, so it should work without the need to insert the token in every url until you close your browser.
I am making a simple Dynamic Website using PHP, where i allow the user to login and then access specific pages. So here's what i have done so far.
The logged in values are taken though $_POST variables in a php script where it fetches values from database for registered users. If the user is found i do the following:
session_register('userid');
$_SESSION['userid'] = $username;//this is taken from $_POST
$_SESSION['accesslevel'] = $access;
at the beginning of the php script i have put session_start();
Now here comes my problem.
At every page now i have to check if the user is allowed to view that page or not, if he ain't then he must be redirected to login.php, if he is then the page load must continue.
Now so far what i have learnt is that only way to maintain values across php pages is to use $_SESSION variables, and which ever page i am using Session Variables i must write session_start() on each page as the first line, else i will be getting Headers Already Sent error..
Strangely i exactly have done that but still get erros with the "headers already sent".
SO i want to what is the best way to design a website, where i have to use Session variables across most of the pages, and keep these common checks at a common place..
Can i use include() feature some how?
Are sessions only way to communicate data across php pages.
What is a better way?
I have the following code :
<?php
session_start();
if(!isset($_SESSION['user']))
{
$_SESSION['loc'] = "adminhome.php";
header("location:ettschoollogin.php");
exit();
}
?>
Which resides on top of every page which wants to check if the user has logged in.
And this is teh script to check for login
<?php
session_start();
include("connection.php");
$userid =$_POST['userid'];
$userpwd =$_POST['userpwd'];
$query="Select UNAME,UPASSWORD,SCHOOL,uaccess from schooluser where uname = '$userid'";
$result=mysql_query($query) or die("couldn't execute the query");
$row=mysql_fetch_array($result);
$useraccess = $row["uaccess"];
$school =$row[2];
if(($row[0]==$userid)&&($row[1]==$userpwd))
{
session_register('userid');
$_SESSION['userid']=$userid;
$_SESSION['school']=$school;
if($useraccess =="admin")
{
header("Location:adminhome.php");
}
if($useraccess !="admin")
{
header("Location:school_main.php");
}
}
else
{
header("Location:ettschoollogin.php?err=1");
}
?>
i was aware of the common error of having extra spaces after "?>", BUT I STILL GET IT.
Thanks guys, i missed out and the "connection.php" file actually had extra spaces after "?>" i had removed it before, but some how the file got rewritten again.Thanks a lot.
Yes, you can use include. Put all your common functions in a separate php file and "include" it at the top of each file.
You can use cookies to store information (typically just an id that you use to look up additional information in the PHP page). Normally, PHP sessions are handled using cookies though. See setcookie in the docs.
You are probably getting the error messages due to stray characters outside of a <?php ?> block. A common error is to have an extra blank line at the end of an include file, after the ?>. That blank line will be output and your headers will have been sent. If that isn't the problem, you will just need to make sure you move the session related code above any code that might generate some output (eg by using print or echo).
•Can i use include() feature some how?
Yes. You can do whatever you want before your session_start() call, only, you must not have outputted anything, not even a single space or character. Probably you have already outputted something, maybe on an automatic inclusion or apache prepend.
•Are sessions only way to communicate data across php pages.
•What is a better way?
Other ways are cookies, post and get parameters. But sessions are the only way to securely pass data among pages without sending them to the client and back (which may pose security risks)
Write ob_start(); at the top of your code and then you dont get the error of "headers already send"