im building my first dynamic site. i have an index.php that based on whether the following session variable is true or false
if($_SESSION['loggedIn'])
{
include 'logged-in/logged-in.php';
}
else{
include 'not-logged-in/not-logged-in.php';
}
the not-logged-in.php displays some forms so you can either login or register this calls a function within an included php file. if the login() function validates via login via mysql it sets
$_SESSION['loggedIn'] = 1;
header("Location: ../index.php");
i however get this error...
Warning: Cannot modify header information - headers already sent by (output started at //index.php:8) in //not-logged-in/not-logged-in.php on line 5
sorry i '*' out the url to keep my project private.
i come from a simple graphics programming background and so this is all new to me. any tips or advice would be greatly appreciated.
This error is caused by having something output to the browser, either with echo, print, etc. before you call the header().
Personally I wouldn't use a session variable to store whether the user is logged in or not because you may want to disable a user, and if they're already logged in they will still have access until their session expires. I like to store the username and hashed password in the session and then re-run the login procedure, using these details, for each page.
this error happens when you're trying to send an http header (like the Location in you code) after there is some kind of output. Check your code and verify your are not sending intentionally any output before sending this header (or even the session_start()). also, if you're using the php closing tags, be sure to not have a single space or newline after it, because it counts as output
Related
I am getting pretty annoyed with an issue with my log in and register scripts that are not working. The funniest thing is that for two weeks ago I used the exact same scripts in another website in another server and it works awesome!
ISSUE
When I try to register or log in I am not redirected to the page I was supposed to be. On register.php the user gets registered (I can see it on the database) but I am not redirected to the login.php, instead the script get's crashed on the message "redirecting you to xxxx.php". Here you can read my scripts.
I took contact with my server (ipage) and asked if something was going wrong with their system. I got 3 different and crossed answers:
1st) I was able to replicate your issue. I did some preliminary troubleshooting and was not able to get to the root cause of the issue.
2nd) They answered me later that they were able to register new users and log in with no problem
3rd) Final answer was that the issue was on my scripts
I am not sure of what is happening here because the scripts are not working (on the opposite to what they say). I wonder if they are lying because they simply are no good or can't find out the cause of the problem. Anyway, the error log says the following:
*"20131014T033118: url.org/folder/login.php
PHP Warning: session_start(): Cannot send session cookie - headers already sent by (output started at /hermes/bosweb26a/b366/ipg.domainname/folder/folder/common.php:1) in /hermes/bosweb26a/b366/ipg.domainname/folder/folder/common.php on line 77 "*
Line 77 is: header('Content-Type: text/html; charset=utf-8');. If I take it out, the error just passes on to another line...
Presuming that I already debugged the scripts and found no error, could this be due to the server's quality? (PHP version f.i.?)
You can put session_start() on the first line ok common.php
You need to make sure session_start() is called before calling header(), or echoing any content. So in login.php, you need to make sure session_start() is either at the top of the page, or you need to move it so it is called much earlier in your script, at least before any header() calls.
Just switch round session_start and header('Content-Type: text/html; charset=utf-8'):
// This initializes a session. Sessions are used to store information about
// a visitor from one web page visit to the next. Unlike a cookie, the information is
// stored on the server-side and cannot be modified by the visitor. However,
// note that in most cases sessions do still use cookies and require the visitor
// to have cookies enabled. For more information about sessions:
// http://us.php.net/manual/en/book.session.php
session_start();
// This tells the web browser that your content is encoded using UTF-8
// and that it should submit content back to you using UTF-8
header('Content-Type: text/html; charset=utf-8');
Have you got a space before <?php as the top of common.php? If you do you need to remove it.
Personally i use ob_start(); after the session_start(); and ob_flush() at the end of the file;
I have an HTML page that I do not want to be available unless the login is successful. My login starts a session, however I don't know how to check for the session in the HTML and if the session exists I want to display the page, if not I want to display a unauthorised message. How can I do this?
You can't check for the session in the HTML per se you'd have to do it in PHP. Depending on how your page is built using PHP you could try putting something like this at the top of your HTML file:
<?php
if (!isset($_SESSION['my_login_var'])) {
echo 'Unauthorised';
exit();
}
?>
But you'd be far better off doing this earlier on in your PHP code, in which case you could use the header function to send the user to a proper 403 page.
UPDATE
Usually PHP does some processing before the HTML is outputted and the headers are sent to the connecting client, so you want to send a 403 header before that output happens. This could be in an included PHP file that is run before the HTML is built, or even in the HTML file itself if no other content has been outputted before the script reaches that point.
You can make a small adjustment to the code above to send a 403 header and 'properly' deny access to the page:
<?php
if (!isset($_SESSION['my_login_var'])) {
header('HTTP/1.1 403 Forbidden');
exit();
}
?>
You're going to need to look up PHP sessions. See http://us.php.net/manual/en/function.session-start.php for PHP session_start() documentation.
Basically you will need to do session_start(). If the login is successful, set a session variable like $_SESSION['logged_in'] = true;. Then do some logic on your page and redirect/display message depending on the result.
You should attempt something and come back and ask a more specific question if you have problems.
I think I forgetting something in my code but can't find what.
On my server I have simple logging.php file.
If I pass user/password parameters then a new session is created.
If I pass loggout the session is destroyed.
If I pass report the list of current session variables are reported on screen.
If I test the code writing urls in my browser all works fine. First invoke .../logging.php?user=xxx&password=xxx. The session is started and the session variables are reported to me. And finally I destroy the session passing the logout parameter.
If user request a report or a logout and no session exists a HTTP-401 error code is returned to client.
On the other hand I have a piece of JavaScript code that I can inject on web page using a bookmarklet. Once code is injected I show a toolbar where user can write user/password and send to server.
The logging actions seems to works fine, and server returns me a 200 status code, but later if I make a request to logout the server returns me a 401 error, which mean no session exists.
I was using chrome and looking at HTTP request and responses can see that when I logging the server returns in the response different values for PHPSESSIONID.
That means two different AJAX request are considered different sessions. The server seems to not recognize the second request from AJAX as if it was started by the same client.
Repeat, the PHP code works fine if I execute using browser directly but not with AJAX request, so I think I forgetting something in AJAX.
Any ideas?
Thanks in advance.
Update
To be more concise, my problem is calling php from JavaScript. It seems there are no sessions started.
Imagine a very simple PHP code:
logging.php: given a user/password starts a new session and also stores 'user' names as a session variable.
request.php: which returns the user name stored as session variable.
logout.php: which destroys the session.
My first AJAX request start a PHP session. That seems fine because a PHPSESSIONID cookie is returned from server. Also I store the user name as session variable.
The second AJAX request tries to get the user name (stored in the session) but it gets nothing and in addition a new PHPSESSIONID cookie is returned from server.
I know it seems impossible and more when I'm testing using browser url request and works fine, but it's the truth.
I'm forgetting something on AJAX, expiration times or something similar?
Update again
I made some tests and I found the problem but not the solution.
My JS code is injected through a bookmarklet.
When I inject the code in a HTML page from my server, the AJAX requests works fine. The first (logging) request gets a PHPSESSID which is passed in subsequent request to the server.
On the other hand If I load google.com and inject the code, the first (logging) request gets the PHPSESSID too but later it is not sent with next requests.
Anyone has experienced the same issue? which is the problem?
Thanks in advance.
Update again, again
Ok finally I found my problem. Because my JS is injected from a different domain (current page is from domainA and my JS code comes from domainB) cookies are not cross domain, so PHPSESSID can be shared.
A possible soulution is when I logging I will return the PHP session ID in pice of JSON data and use it for subsequent calls.
If I'm correct, you're trying to log in a user by making an AJAX request to a URL, with the username and password provided in the URL? That's not really a safe construction, the password is very vulnerable this way?!
I would advice you to implement jQuery, and transer the login details using the $.POST command:
http://api.jquery.com/jQuery.post/
Make sure all your files (also those requested by AJAX) contain session_start(); on top of the file.
When every file contains session_start(); and you're using the same $_SESSION variables to check if a user is loggedin, it should work!
Are both of your AJAX requests coming from the same page? The requests are Asynchronous, so it may be that the "logged in?" request is returning its result before the "log in" request goes through.
From what you have asked, I hope your code is (at its beginning more or less) something like:
A file logging.php like this:
<?php # file : loggging.php
if(!ini_set('session.auto_start'))
// more stuff
if(!empty($_REQUEST['user']) && !empty($_REQUEST['passwd'])) {
session_regenerate_sid(); // This is important (1)
$_SESSION['user'] = $_REQUEST['user'];
// Whatever
}
A file request.php like this..
<?php # file : request.php
if(!ini_set('session.auto_start'))
// Whatever stuff to process data
var_dump($_SESSION);
// Or a nice foreach($v as $i => $x) {
// echo("[$i] => $x\n<br />");
// } instead :)
And your logout.php should read something like..
<?php # file : logout.php
if(!ini_set('session.auto_start')) session_start();
session_destroy();
You are probably not calling either session_start() or you are calling it twice.
To check this out try this: change all your session_start() lines for:
session_name('MYCoolNewName');
session_start();
Now your session should not read PHPSESSID, instead it should be MYCoolNewName.
If it is not, then your problem is the aforementioned.
(1) I put as important session_regenerate_sid() because opened authenticated sessions are a threat out there. I'll demonstrate it with an example.
Alice visits coolwebsite.com/login.php, which gives her a SID which I'll call AliceSID.
Alice tells Bob to visit coolwebsite.com/login.php?PHPSESSID=AliceSID, and when Bob does Alice could log in his account unless Bob's session was regenerated.
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"
I have a login form in every page of a website so the user can login from everywhere. I have a login.php file that I refer to it from the form (using 'action').
I use $_SERVER['HTTP_REFERER'] to redirect the user to the same page he logged in from when he succesfully log in or when he logs out.
But if there was a problem logging in, how can I send an error to the same page he is trying to log in?? I have tried sending the error using $_GET, like this:
// process the script only if the form has been submitted
if (array_key_exists('login', $_POST)) {
// Login code goes here...
// If there was a problem, destroy the session and prepare error message
else {
$_SESSION = array();
session_destroy();
header('Location: '.$_SERVER['HTTP_REFERER'].'?error');
exit;
}
But the problem is that a lot of pages in the website are like this details.php?mid=0172495. They already recive information from the $_GET method and for security reasons I cant use another $_GET method...
So, How can I pass the error???
Thanks...
Since you're already using sessions, after you destroy the session why not create a new one with $_SESSION['error'] or something similar set? Or alternatively simply don't delete the session at all but set the error which you can immediately check in other pages?
To add to what Chad Birch said...
In your login script where you redirect, check the HTTP_REFERER value for the character '?'. If it is present, append '&error' to the HTTP_REFERER and redirect to that. Otherwise append '?error' to the HTTP_REFERER and redirect to that.
I'm not sure what exactly you mean by "for security reasons I cant use another $_GET method", but in the case that there's already something in the query string, you just need to append another variable to it, instead of replacing it.
That is, if the address is like details.php?mid=0172495, you should be sending them to details.php?mid=0172495&error, whereas if it was just details.php, you send them to details.php?error.
Another way of doing what you need is to include your login.php file in every page that has the login form and just post to that same page. So you won't need any redirection at all.
This maybe is not a good scalable and maintainable solution, but it is simple. It all depends what kind of app you are writing. But you are saying that you are new to php so you can start like this. You can always go fancy later...