I have a form in a page .Now I am submitting the form to the same page(using post).This part works well. But when I refresh the page, the form is submitted again.Any clues on how to fix this.
Do a header redirect to either the same page or another page.
Redirect back to the same page after processing the POST request.
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
# process the request ...
# ... and redirect
header('Location: page.php');
}
You can work with sessions. If the form name exists in the session, you don't handle the form again.
$_SESSION['form']['name_of_the_form'] = time();
As the others have noted, you can use a HTTP redirect by modifying the headers sent back to the user's browser. The header() function in PHP allows you to do this. Be sure that you execute this function call prior to outputting anything, otherwise it will fail. It could look something like the following.
<?php
// some code to process the form data here
header('Location: page.php'); // redirect user to page.php
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.
Basically, I am checking to see if the user is logged in and if not I will use header('location: login.php') to redirect to the login page.
I am confused if the browser is actually redirecting or the server? If it is the browser then would it be possible for the user to prevent the browser from redirecting and view the contents of the page?
Yes, it is not the browser that is re-directing, but php before anything is sent to the browser.
Just make sure you use exit() after your header call and that nothing is outputted to the browser before your header call.
If by "enough", you mean that the information will not be exposed to anyone who is not authenticated, even if they sniff the network traffic, then you must simply not send the information in the body of the response to any non-authenticated request.
Something like this should be enough:
header('location: login.php');
exit; // make sure not to echo anything in the body
It will cause the browser to receive an HTTP header and start a totally new request to login.php, while not revealing any of the sensitive info in the response.
Well, keeping it simple, checking for specific variable and based on it , deciding for redirect / showing contents is okay...something like this will work for you..
if(your condition){
header(Location: login.php)
exit() or die() ;
}else{
show contents.....}
The server is redirecting. The client browser gets directed to the page the server sends through the header modification. The user is not able to prevent the redirection from the page, but is able to see content after that line of redirect code header('location: login.php');
// print to error log before and after header redirect to show code is executed after the redirect
error_log("before redirect");
header('location: login.php');
// this will get get executed. To prevent, exit() script immediately after the header redirect
error_log("after redirect");
I have a PHP site (with CodeIgniter) that includes a registration form. I have a page with some details, which links to the form on a separate page. The form posts to a third URL which does the processing and redirects back to the first page if it's successful (or the form page if not).
Currently I am adding a parameter for success: example.com/page?success=1 which shows a success message. The problem is that some people have been sharing this URL (and clicking the Facebook Like button) so when another user opens that URL they see a message "thanks for registering!" which they obviously haven't done yet.
I thought this was the standard way of doing forms (submitting to one URL and redirecting to another) but is there a better way? I don't want to post back to the same page because then you get the POSTDATA warning when trying to reload the page.
You have three ways to do this
The way you're using
Not actually redirecting but sending request(s) with AJAX
SESSION (or, in edge case, cookies)
If you select to use SESSION, you can just assign a session variable to true
$_SESSION['registered'] = true;
and checking it on the first page
if (isset($_SESSION['registered'])) {
unset($_SESSION['registered']);
// shot the message
}
Typically you would set your flag for success in the session to display this message when the next page loads. This is commonly referred to as a Flash Message. You would then check the value/existence of this session flag and show your message or not accordingly. In most frameworks there is built in functionality for this which includes the clean up of the flag on the next request so that the message is only displayed directly after the action generating it is taken.
From the CI Sessions Documentation:
CodeIgniter supports "flashdata", or session data that will only be
available for the next server request, and are then automatically
cleared. These can be very useful, and are typically used for
informational or status messages (for example: "record 2 deleted").
Note: Flash variables are prefaced with "flash_" so avoid this prefix
in your own session names.
To add flashdata:
$this->session->set_flashdata('item', 'value');
You can also pass an array to set_flashdata(), in the same manner as
set_userdata().
To read a flashdata variable:
$this->session->flashdata('item');
If you find that you need to preserve a flashdata variable through an
additional request, you can do so using the keep_flashdata() function.
$this->session->keep_flashdata('item');
You should have some verification checks in your code that handles the processing of the form data to make sure that the required fields are filled out. Otherwise, you should be redirecting to your first page to have the user fill out the form.
Also, this could be handled via AJAX, but that would be a second step to having the proper verification in your form-processing page
HTML:
<form method="post">
<input type="text">
<input name="submitted" type="submit">
</form>
PHP:
if($_POST['submitted']{
//post was submitted process it
if(/*whatever you're doing to the form succeeds*/){
//show success
}
}
POST will not show variables in the URL.
Several solutions here, one would be to check for the form submission and if it hasn't been submitted redirect to the page with the form on it.
ie:
<?php
if (isset($_POST['submit']))
{
// process the form
}
else
{
//redirect to the form itself
header( 'Location: http://www.yourform.com' ) ;
}
?>
i am trying to send header from a php file that is called with ajax. problem is, when i validate all information with php, i want to redirect to another page but headers dont work! any ideas?
what the code does:
//------------- index.php
on click of input, function passes <input> values through $_POST to login.php
if($_SESSION[superman]==true){redirects to index_main.php}
//------------- login.php
all it does is validate forms and if login and password are correct, it sets $_SESSION [superman]=true
The redirect will only redirect the Ajax call! If you want to change the displayed page in the browser, you'll need to redirect using Javascript once the Ajax call completes.
Make your Ajax call return a value indicating successful login (for example the string true or maybe the URL to the page you want to load)
Check the return value of the Ajax call. If success, change location.href using Javascript.
I have several forms brought in via jQuery .ajax funciton. In the parent page I start a session like this
<php
session_start();
$_SESSION['authenticated'] = 'yes';
?>
then in the form that is loaded have a check like this:
<?php
session_start();
if($_SESSION['authenticated'] != 'yes') {
header("Location: http://www.google.com");
}
?>
I know its not the best, but it's an attempt to stop people form accessing the forms directly. The problem is that if you go to the parent page, then you can enter the form URL and get there because the session was started when you hit the parent page. How can I destroy the session or remedy this issue?
Effectively, you can't.
To make it more complicated, don't request the form URLs directly. Try to request authorize tokens per request of the main page:
If you generate the main page and you know the form to be requested beforehand, then generate tokens e.g. using md5(time().rnd()), associate each with one you your forms and save the association in your session
Then, your JS code won't request the form URLs, but a factory script using a token injected into the JS code
If you find the token in your saved association in your session, emit the form and delete the token in your session.
This way, each form can only be requested once by one preceding call of the main page.
Note, that this isn't fully safe too: If a user requests the URL of the main page using wget, he can request each form once.
You can check $_SERVER['HTTP_REFERER'] in your form .php code to see where the request is coming from. An AJAX call will set the HTTP_REFERER to the page it is called from.
if (strpos($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST']) === false) {
die();
}
It's not a bulletproof solution. Any page that is publicly accessible can be retrieved by an automated script.