Octobercms - CSRF Protection on a form to preventing multiple submission - php

I have a component with a form and then code to handle the submission. The problem is, if I spam the button it will submit the form multiple times. A solution to this would be to add a disabled state via Javascript to prevent the user from doing this.
From a security reason I do not want this to happen at all and prevent server side. I have a token and in the config I have CSRF enabled
'enableCsrfProtection' => true,
Here is my form
{{ form_open({ request: 'onSubmit' }) }}
<div class="form-group">
<label class="control-label" for="subject_name">Subject's name</label>
<input id="subject_name" name="subject_name" type="text" placeholder="" class="form-control input-md" required="">
</div>
<div class="form-group">
<label class="control-label">Postcode</label>
<input id="postcode" name="postcode" class="form-control input-md" type="text" required>
</div>
<div class="form-group">
<button id="submit" type="submit" value="submit" class="btn btn-lg btn-gold pull-right"><i class="fa fa-lock"></i> Request Job</button>
</div>
</form>
and in the generated html
Handler/ Session / Token
<input name="_handler" type="hidden" value="onSubmit">
<input name="_session_key" type="hidden" value="7Eg9bK4pcT2NOgWwUS0UFUckjkSMRC1UDBkBhPwO">
<input name="_token" type="hidden" value="00nbkK3EAo2I8WGWSh85qkMjHYig6aldrd3oe8HZ">
Then in my components code
public function onSubmit()
{
$name = post('subject_name');
$postcode = post('postcode');
if (Session::token() != Input::get('_token'))
{
/* Invalid token */
return print('Token invalid');
}
$job = new Job;
$job = $job->name = $name;
$job = $job->postcode = $postcode;
$job->save();
}
Yet I spam the submit button and it will execute multiple times. How can I add the ability to only execute once?

What you need is a loader
https://octobercms.com/docs/ui/loader
<div class="loading-indicator-container">
<button id="submit" type="submit" value="submit" data-load-indicator="Saving..." class="btn btn-lg btn-gold pull-right"><i class="fa fa-lock"></i> Request Job</button>
</div>

There are numerous solutions to what you want done.
My suggestion the most eloquent solution is a redirect or an ajax update. Communicate with your users by replacing the form with a message that says your "Request has been submitted. Thank you." This will stop them from being able to spam the submit button.
You could do something with the session like advised by Magnus. Make sure to include a timestamp so it can be removed after some time.

Related

codeigniter signin or signup from same form

I am trying to implement "signin or signup" form in codeigniter.so its one form which accepts email and password and POST to below controller.
Expectation : check if email is duplicate, if exists, Post email,password to login method, else post email,password to register method.
Current behaviour: it checks for duplicate and posting validate error as email already exits and never login.
Here is my user controller logic
public function index()
{
$email = $this->input->post('email');
$password = $this->input->post('password');
$this->form_validation->set_rules('email', 'Email', 'is_unique[user.email]');
if( $this->form_validation->run() === FALSE)
{
$this->login($email,$password);
}
else { $this->register($email,$password);}
}
As per Alex's comment, using single button will create unwanted user accounts when user typed email address wrong, so we decided to go with 2 submit buttons(signin,signup) for 1 form which is working as expected with minimal effort and clean UX. just formaction html tag will do the trick!!.hope this help someone!
<form class="row" name="regform" action = "<?php echo base_url()?>user/login" method="POST">
<input type="hidden" name="ref" value=1>
<div class="col-md-6 col-lg-3"> <input type="email" name="email" placeholder="Email Address"> </div>
<div class="col-md-6 col-lg-3"> <input type="password" name="password" placeholder="Any Password"> </div>
<div class="col-md-6 col-lg-3"> <button type="submit" class="btn btn--primary type--uppercase" name="signup" value="signup" formaction = "<?php echo base_url()?>user/register">Signup</button> </div>
<div class="col-md-6 col-lg-3"> <button type="submit" class="btn btn--primary type--uppercase" name="signin" value="signin" formaction = "<?php echo base_url()?>user/login">Signin</button> </div>
</form>

Laravel 5 Form Submit to View

I'm recoding my website and moving over to Laravel but for some reason I can't figure out how to have a search form that redirects you to a profile page.
<form class="navbar-form navbar-right search" role="search" action="/profile/" method="GET">
<div class="input-group">
<input type="text" class="form-control navbar-player-search" placeholder="Enter IGN here" autocomplete="off" required>
<div class="input-group-btn">
<button type="submit" class="btn btn-default">
<i class="glyphicon glyphicon-search"></i>
</button>
</div>
</div>
</form>
I have a route already set up which works if I went to example.com/profile/Callahan
Route::get('/profile/{Profile}', 'PlayerController#getStats');
but I need the form to do that same thing.
Is it possible to do this with default laravel 5.4.3 or do I need something like https://laravelcollective.com/docs/5.3/html?
I don't understand exactly the information which the input contains, but I'll consider this:
The user will write in the input and click on search.
Then, in your controller, you'll get the profile name after the search and redirect to the profile. Is that the case?
If yes, you should do something like that:
Routing
Route::get('/profile/{Profile}', 'PlayerController#getStats');
Route::get('/search', 'PlayerController#searchForm');
Route::post('/search', 'PlayerController#search');
Controller
public function searchForm() {
return view('search');
}
public function search(Request $request) {
// get the input
$inputText = ...;
// logic to get the profile name
$profileName = ...;
return redirect('/profile/'.$profileName);
}
View
<form class="navbar-form navbar-right search" role="search" action="/search" method="POST">
<div class="input-group">
<input type="text" class="form-control navbar-player-search" placeholder="Enter IGN here" autocomplete="off" required>
<div class="input-group-btn">
<button type="submit" class="btn btn-default">
<i class="glyphicon glyphicon-search"></i>
</button>
</div>
</div>
</form>
Once again, I don't know if it's what you really want, but if it's not, let me know to try help you again.

Is it safe to call php service from onClick?

What I want know that is that when form data is POST to a php service directly from onClick="insert.php" then is it safe. Please explain your answer with details.
for example:
<form role="form" method="POST" enctype="multipart/form-data">
<div class="form-group">
<label>User Id</label>
<input class="form-control" name="First Name">
</div>
<div class="form-group">
<label>City Id</label>
<input class="form-control" name="Last Name">
</div>
<button type="submit" class="btn btn-primary" onclick="allowStory.php">Allow</button><button type="submit" class="btn btn-primary" onclick="insert.php">Insert</button>
</form>
It also return to same page by executing php service as I wanted. But question is that is it safe? and is this type have any drawback? if yes then what are those?
Putting a filename in onclick doesn't do anything, the onclick attribute has to contain Javascript code.
If you want a submit button to go to a specific script instead of the action of the form, use the formaction attribute.
<button type="submit" class="btn btn-primary" formaction="allowStory.php">Allow</button><button type="submit" class="btn btn-primary" formaction="insert.php">Insert</button>
It's perfectly safe to do this, it's no different from specifying the action of the form in the action="scriptname.php" attribute of the <form> tag.
Use following HTML
<form role="form" method="POST" id="formsend" enctype="multipart/form-data">
<div class="form-group">
<label>User Id</label>
<input class="form-control" name="First Name">
</div>
<div class="form-group">
<label>City Id</label>
<input class="form-control" name="Last Name">
</div>
<input type="submit" name="submit" value="Submit" /></form>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
$(document).on('submit', '#formsend', function()
{
$.post('savedate.php', $(this).serialize(), function(data)
{
$("#sent").html(data);
});
return false;
});
and create a savedata.php or any other name and put your php code to save data in it. you can not give filename to onclick event

Submit Button Only Working on Index Page

Been having trouble with a form not submitting data to a page (Change Password) when on any page of the website apart from the index page (Which is working as it should). The website is built using CodeIgniter.
The code currently used on all pages for the form is the following:
<div class="modal-body">
<form role="form" id="change_password_form" action="<?php echo base_url('auth/change_password')?>" method="post">
<fieldset>
<div class="form-group">
<input class="form-control" placeholder="Old Password" name="old" type="password" autofocus>
</div>
<div class="alert alert-danger" id="old" role="alert" style="display:none"></div>
<div class="form-group">
<input class="form-control" placeholder="New Password - minimum 8 characters" name="new" type="password" value="">
</div>
<div class="alert alert-danger" id="new" role="alert" style="display:none"></div>
<div class="form-group">
<input class="form-control" placeholder="Confirm New Password" name="new_confirm" type="password" value="">
</div>
<div class="alert alert-danger" id="new_confirm" role="alert" style="display:none"></div>
<input type="hidden" name="user_id" value="<?php echo $user_id;?>" id="user_id" />
</fieldset>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="changepassword" value="Submit">Submit</button>
</form>
</div>
On the index page, this successfully goes to the change_password function and will check the details to see if they meet the rules. An error message is shown below the text box when submit is clicked. However on other pages using the same code, nothing happens when submit is clicked. when I go into Main.php and change the page of index.php in the index function to any other page (view_inventory.php for example), The change password works correctly on the new index page, but will not work on the old index page.
I can get the change password to work on other pages if I replace the submit button with the code below (Doesn't show the results under the text boxes, but on a new blank page), but I didn't really want to have to edit so many pages if it can be fixed in a smaller amount.
<input type="submit" value="Submit" class="btn btn-primary">
Any help would be gratefully appreciated.
I had the same error last week. you have to use a Submit inside form instead of button.
You can use form_submit for example:
echo form_submit('mysubmit', 'Submit');
// Would produce: <input type="submit" name="mysubmit" value="Submit" />
Here is the documentation:
http://www.codeigniter.com/user_guide/helpers/form_helper.html
Regards.

Multiple form authentication in the same domain

I have a website with two form authentication in different pages, have different input name and link to different pages . The problem is that when I save my authentication to a browser (chrome) of a form , the browser fill in the fields with the same data in the other form . How is it possible?
First form
<form action="" method="POST" enctype="multipart/form-data">
<div class="form-group">
<label for="exampleInputEmail1">Email</label>
<input type="email" name="private_email" class="form-control" id="email1" value="" placeholder="Enter email" required>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" name="private_password" value="" id="password1" placeholder="Password" required>
</div>
<input type="submit" name="login" class="btn btn-default" value="Login">
</form>
Second Form (It is a form of a cms)
<form action="http://escuolainsieme.it/shop/login" method="post" id="login_form" class="box">
<h3 class="page-subheading">Sei giĆ  registrato?</h3>
<div class="form_content clearfix">
<div class="form-group form-ok">
<label for="email">Indirizzo email</label>
<input class="is_required validate account_input form-control" data-validate="isEmail" type="text" id="email" name="email" value="">
</div>
<div class="form-group">
<label for="passwd">Password</label>
<span><input class="is_required validate account_input form-control" type="password" data-validate="isPasswd" id="passwd" name="passwd" value=""></span>
</div>
<p class="lost_password form-group">Hai dimenticato la password?</p>
<p class="submit">
<input type="hidden" class="hidden" name="back" value="my-account"> <button type="submit" id="SubmitLogin" name="SubmitLogin" class="button btn btn-default button-medium">
<span>
<i class="icon-lock left"></i>
Entra
</span>
</button>
</p>
</div>
</form>
Login.php
<?php session_start(); // Starting Session
$error = ''; // Variable To Store Error Message
if (isset($_POST['private_login'])) {
if (empty($_POST['private_email']) || empty($_POST['private_password'])) {
$error = "<div class='alert alert-danger'>Compila tutti i campi</div>";
} else {
$email = mysqli_real_escape_string(conn(), $_POST['private_email']);
$password = mysqli_real_escape_string(conn(), $_POST['private_password']);
$cls_utente = new utente();
if ($cls_utente->check_user($email, $password) == 1) {
$_SESSION['login_user'] = $email; // Initializing Session
$_SESSION['is_logged'] = true;
} else {
$error .= "<div class='alert alert-danger'>Email o password errati</div>";
}
}}?>
You can try using autocomplete="false" or autocomplete="off" to disable it, not sure if it will work but give it a try.
As far as i am concerned it's not possible to make the browser 'realize' that they are different forms and they should not be auto-filled with the same data.
Have a look at these 2 answers, answer1 answer2 for more information how browser detects the forms.
You must add another one column in your user table, example if you add type column the value set default super admin,moderator, user. Now you can check the login authentication with this column.If user-name and password and type is equal redirect to particular page.so you can redirect different page depends upon the user type..

Categories