Sending POST Request to Secured Action - php

I have an action that takes POST data secured by sfGuard. This means that if the user is not logged in, the POST data will be sent to the log in form. Ordinarily, this is not a problem, the user continues to log in, and has to submit the data again.
Unfortunately, the log in form seems to be using the POST data as if it was submitted with the form itself. This means that it is complaining that the required username and password fields are missing, and it complains that it is missing a CSRF token. This last problem does not go away, after submitting the form, meaning the user cannot log in, anyway.
The user should not be presented with the form if not logged in, but it might be possible for the user to log out with the form still open. So I am asking in the interest of keeping the interface watertight and error-free.
Is this a shortcoming of sfGuard, can it be avoided, or am I doing something wrong altogether?
To clarify, the route looks like this:
add_subgroup:
url: /group/:id/add
class: sfPropelRoute
options:
model: Group
type: object
param: { module: subgroups, action: create }
requirements:
group_id: \d+
sf_method: [post]
The form used to submit the request is as follows:
<form action="<?php echo url_for('add_subgroup', $group) ?>" method="post">
<input type="hidden" name="group_id" value="<?php echo $group->getId() ?>" />
<input type="text" name="subgroup_id" />
<input type="submit" class="button" value="Add" />
</form>

It is a shortcoming of sfGuard, because the signin action will check for a POST request, and if so bind the form.
From the code in BasesfGuardActions.class.php:
if ($request->isMethod('post'))
{
$this->form->bind($request->getParameter('signin'));
I'm personally not a big fan of forwarding between actions in symfony, and just like in this case, I think it's more appropriate to redirect than forward. This also solves your problem because this will result in a new GET request. You can accomplish this behavior by extending sfGuardBasicSecurityFilter.
class mySecurityFilter extends sfGuardBasicSecurityFilter
{
protected function forwardToLoginAction()
{
$context = $this->getContext();
// If you want to redirect back to the original URI (note: original POST data will be lost)
$context->getUser()->setReferer($context->getRequest()->getUri());
$url = sfConfig::get('sf_login_module') . '/' . sfConfig::get('sf_login_action');
$context->getController()->redirect($url);
throw new sfStopException();
}
}
Now in app/myapp/config/filters.yml
security:
class: mySecurityFilter

This is probably because you put the code of auth the login data in the same action (probally by check whether the request is post).
However You could divide the one action into two actions. One for showing the login form, and the another is for auth the user's login data. And set your secure_action to the action which is just to show the login form.

Related

How can I hide user's id and password from URL?

Hello I have a web page where users can view and edit their application information. I have an Edit button. When a user clicks on this button it takes him to an edit page. Here is my code:
<form name="form3" method="post" action="pages/application_edit.php?id=<?php echo "$id[0]";?>&pwd=<?php echo "$pwd";?>">
<input type="submit" name="Submit" value="Edit Application" class="button">
</form>`
After a click the user sees this URL:`http://website.com/pages/application_edit.php?id=1&password=Flower1
How can I hide the password from the URL?
Instead of sending the values as $_GET values, send them as $_POST values to that PHP page.
<form method="POST" action="pages/application_edit.php"> // no need for the URL query string
In the PHP file
<?php
$user_id = $_POST['id']; // similar to how you'd use $_GET
....
Although the way you're approaching this is wrong, you shouldn't be passing these values between pages. At the very least your username/id should be stored as a session variable and information should be accessed when required from a database.
Either way, that's how you can send them without having them "visible".
It seems you lack session control routines.
You should manage all private options of your application (the ones you are able to perform only - and just only - when you are logged in) inside a session to avoid exposing user credentials.
You can start learning about it here.
Also, consider encrypting your HTTP requests using SSL certificate.

How to make a form submit only on button click not on refresh?

I have a form where i should make the form submit(request to a service) only if the form field is changed, If the field is not changed when the user refresh the page it should not submit the form again.
OBJECTIVE is to reduce the number of form submission as possible, So if the user has the same entered data and he refresh, we shouldn't waste the previous returned datas and try to give new request and show the same datas.
Instead it should be submitted only if the TEXT(searchdirectory) is changed. So there won't be repeating request for same datas.
<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
<label>TEXT :</label>
<input type="text" id="search_dir" name="searchdirectory"
value="<?php
if (isset($_POST['searchdirectory']))
{
echo($_POST['searchdirectory']);
}
?>"
/>
<input type="submit" value="Search" name="submit" id="searchB"/>
<?php
if (isset($_POST['submit']))
{
//functions to show results queried from searchdirectory
}
?>
</form>
I guess this would be to deal with refresh behaviour of browsers, Is there a way to stop the form submission if user refresh the page. It should show the same datas.
Use redirect when form data was sent at first.
<?php
if (isset($_POST['submit']))
{
//do function
header("Location: http://". $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']);
}
?>
Where "http://". $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] - is a link to which the user will be redirected after form submit.
There is two ways to go. But I try to address your objective, and not your specific question :)
You can forward the browser to a new url after form submit. This is a very normal procedure. So that when your form submits the browser redirects immediately to a normal GET URL. Now if the user hit refresh the form is not submitted again.
2 The other approach that you should use if the form is login dialog etc. Add a one time session key to a forms hidden field, and store the same key in on the server. Now if the user submits the form check that the keys match. If they do accept the submit, and clear the key. If the user now hit F5 again, and you've already removed the key, simply reject the values submitted.
why don't you clear the form after submitting, or add session for each submit request

Object Oriented PHP to pass message to user upon success of function

I am new to OO php so this may seem basic..
Basically I have a list of courses a user can book. I have got it so the user can remove the course from their list, but I want a message to be displayed to them after they delete. I have done something similar to what I want here:
<form name="removecourse" action="<?php bloginfo('url');?>/user/<?php echo $current_user->first_name ; ?>" method="post">
<input type="hidden" value="<?php the_id();?>" name="courseid" />
<input id="removebutton" type="submit" name="removecourse" value="Remove">
</form>
The form sends the required data to the same page, and at the top of that page is a check to see if the forms post name is present in $_POST[] like so:
if(isset($_POST['removecourse']) && !empty($_POST['removecourse'])){
$courseManager->delete_post($_POST['courseid'], $_POST['cancel-reason']);
echo $courseManager->delete_response;
};
This is where the Class and object part comes in...
public $delete_response;
function delete_post($postid, $reason){
//stuff to actually delete the post
$this->delete_response = 'Thanks, your course has been removed.';
}
So here I am adding a value to the delete_response variable and calling it above at the top of the page. This works, but when I refresh the page the message is still there as I am resubmitting the POST. I am just wondering if what I am doing is along the right track, and how to implement a Post/Redirect/Get type functionallity to stop the messaage from appearing on page refresh?
You have to check, either your course has been already deleted, is it simple as that :).
Yours displaying it again because:
if(isset($_POST['removecourse']) && !empty($_POST['removecourse'])){
//is always true when posted again.
}
You have to check the existiance

POST/REDIRECT/GET vs custom implementation

I have some forms, and am currently using an implementation as described below:
<form action="/formpost.php" method="post" name="form1" id="form1">
<input type="hidden" name="to" id="to" value="__COMMENT1" />
<!-- rest of form -->
</form>
__COMMENT1 refers to the page where I want the user to be redirected after the form posts.
Pretty much what happens is that the form is posted to formpost.php, the $_POST array is converted to $_SESSION['POST'], the $_POST is unset, and then the user is redirected to the location referenced in the value of the hidden input field ([id = to] always the same ID/name.) I can then continue to use the user's form submitted values (referenced from the $_SESSION array) regardless of whether they go 'back', refresh, etc.
Is there anything wrong with this?
Are there any benefits to using the POST/REDIRECT/GET pattern instead?
Nothing wrong with your method, it's more convenient than PRG.
though, I see no point in keeping POST variables unless in case of error.
and there is no point in unsetting $_POST, of course.
Well, after some explanation it seems that your setup is quite wrong.
there is no point in making single action for all forms as well as in unnecessary redirect.
make your form action the actual script that validates the form.
on success, redirect wherever you want.
on error:
save POST data and error messages into session and redirect to the same URL
populate the form and unset POST data and errors
show the form

pass value from page to another in PHP

I am sending login status = fail, back to my login page.Here is my code-
header("location:index.php?login=fail");
but that is sending through URL like-
http://localhost/303/index.php?login=fail
is there any way to pass value without showing in URL? And how to get this value on the second page?
You are passing that value via a GET request, which is why it appears in the URL. In order to pass a value without showing it in the URL, you want to pass it via a POST request.
In order to do this you aren't going to want to "return" the value to your login page. Instead, whatever php form is handling the process of logging in the user after they click the "login" button, will decide what to show the user.
In PHP post variables can be accessed by the global $_POST object -
$_POST['username'];
Would get the value with the name "username" that you passed via POST:
<form method="post" action="checkLogin.php">
Username:
<input type="text" name="username" maxlength="25" />
Password:
</td><td><input type="password" name="password" />
<input type="submit" name="submit" value="Login">
</form>
In order to dynamically save and show errors to the user, you can store them in the session, for example have a file called "errors.php"
<?php
if (isset($_SESSION['errors']))
{
echo $_SESSION['errors'];
}
unset($_SESSION['errors'])
?>
And in your php that checks the login, do:
session_start();
$_SESSION['errors'] = "Invalid username or password.";
Then redirect to your login page (don't pass any variables) and on your form always have this field:
<?php include("errors.php"); ?>
If you didn't have any errors, it won't show anything and the login page will look normal.
Note: In any php form that you use a session_start(), it HAS TO BE THE FIRST THING in the form.
Other ways are to use session or hidden fields but you what you are doing is fine for the purpose. You can later retrieve the value like this:
if ($_GET['login'] === 'fail')
{
// failed.......
}
there are several ways to accomplish your task
Modern AJAX way. Form being sent using AJAX. No page reload until password is correct. Errors shown in place. Requres javascript.
Post/Redirect/Get pattern. Form being sent using regular POST. No redirect on errors, shown in place.
sessions, when we store an error in the session

Categories