This might seem like a silly question, but most of the documentation shows the csrf_token being echoed in the view. Is there any difference between doing that vs. generating the token in say a controller and then passing that token to a view?
Is there any difference between doing that vs. generating the token in
say a controller and then passing that token to a view?
All that you are doing is creating an extra step for no reason. Laravel handles the token generation and session side of things.
The csrf_token is automatically included if you use Form::open(), so you dont need to echo it out yourself.
Related
Not entirely confident I have understood security in Laravel forms enough. For example, if a form contains
<input type="hidden" name="user_id">
then obviously a hacker could change the value before submitting an update.
While I have looked here at CSRF, I've not fully understood if this is enough protection?
E.g. Taking the above, if I go to a site and open a form to edit a record I'm permitted to view but not change, and maliciously alter the "user_id", is it enough that the form is protected with {{ csrf_field() }} or must I employ some further security such as Crypt::encrypt($id) to hide the user_id (held in a database) and Crypt::decrypt($id)?
Is it considered a bad practice to expose a row id (like a user id) in a client browser (even though everything is sent over https)?
Many Thanks
No, it's not enough to use just CSRF token in this case. You also need to use policies, guards, middleware to protect your app.
In this case, someone can alter the user_id if you read it from the form and use after that, so you need to use a policy like this one to protect data (this example is from the docs):
public function update(User $user, Post $post)
{
return $user->id === $post->user_id;
}
Also, when you need to use user ID, always use auth()->id() or auth()->user() if you need whole object. Never read user ID from the form.
The Laravel framework stores the value of this CSRF field like a session variable and matches it when you submit it.
When you submit the form Laravel checks that value from the session value stored. if there is a mismatch an error is thrown !
:)
CSRF token protect the site from cross-site requests, means an external user can't duplicate the form and send a post request. Laravel create a random session token which we place in the hidden field using csrf_field() or Session::token() function. Laravel checks the session with hidden field value from the form before processing the form.
Try removing the form action. It should work.
I have a Controller that parses an XML and returns a view with a list of names and URLs.
return view('view_1',compact('myList'));
View_1 will have a form with parameters method="POST" action="goToView_2"
Then I get some information from my view_2 through a POST, but I still want to keep $myList so that view_2 view uses it aswell.
How do I pass $myList from the first view to the next through a controller?
It sounds like you're trying to have multi-step form of some kind.
I would store the data in the session and easily access it in the second controller or in the view (although not recommended).
https://laravel.com/docs/5.4/session#using-the-session
PS. I personally love using the global session helper.
CodeIgniter gives an error "The action you have requested is not allowed." when it fails the check for CSRF. As I understand it, this means the POST is missing the hidden token from the form that proves that an attack is not being done.
The token is generated automatically with a call to the CI form_open function.
In my case, I'm using Knockout to post the contents of a ViewModel for saving, like this:
ko.utils.postJson($("form")[0], self.pages);
I've found solutions elsewhere that simply turn off the CSRF setting for the specific page, but that doesn't seem like a good solution.
Presumably because the token is not being received, the postJson call is not submitting the existing form. Is there a way to either submit the required token along with the JSON data or submit the JSON data with the existing form?
try to use form_open() and form_close
all form helper functions that will help.
or: I think it's from time zone difference as the Security class depends on time for hashing.
I have footer view that's included on all my pages which contains a form. I would like to be able to make use of CI's form validation library to validate the form. Is that possible?
Currently the form posts back to the current page using the PHP_SELF environment variable. I don't want to get it to post to a controller because when validation fails it loads the controller name in the address bar, which is not the desired behaviour.
Any suggestions gratefully received.
Thanks,
Gaz
One way, whilst far from ideal, would be to create a "contact" function in every controller. This could be in the form of a library/helper.
CI doesn't natively let you call one controller from another, although I believe there are extensions that enable this.
Another option would be an AJAX call instead, which would allow you to post to a generic controller, validate etc whilst remaining on the current page.
In this use case, I would definitely go for an AJAX call to a generic controller. This allows you to show errors even before submitting in the origin page.
Another way (slightly more complex), involves posting your form data to a generic controller method, passing it a hidden input containing the current URL.
The generic controller method handling your form can then redirect to the page on which the user submitted the form, passing it the validation errors or a success message using flash session variables: $this->session->set_flashdata('errors',validation_errors()) might do the trick (untested)
The good thing about this is that you can use the generic form-handling method for both the ajax case (suppressing the redirect) and the non-ajax case
AJAX would be best, just like everyone else says.
I would redirect the form to one function in one controller, you could make a controller just for the form itself. Then have a hidden value with the return URL. As far as errors go you could send them back with flashdata.
Just remember to never copy paste code, it a bad practice and guarantees bugs.
//make sure you load the proper model
if ($this->form_validation->run() == FALSE){
// invalid
$redirect = $this->input->post('url');
$this->session->set_flashdata('errors',validation_errors());
redirect($redirect);
} else {
/*
success, do what you want here
*/
redirect('send them where ever');
}
I am trying to code my first codeigniter project. I have a login controller which basically filters the data inputed and calls a model function that checks if the user is found in the database.
What I am trying to do is reuse this controller on the index page. So basically I want to be able to do user login on the index page or on the normal controller page (index.php/login/) without code duplication.
I'm sure there is an easy way to do this, but I'm not sure what the best solution is. Make it a library?
Thanks!
For this I would simply make the form in your view post to the login controller.
As a more generic way to share code and logic throughout your application, take a look at this article:
CodeIgniter Base Classes: Keeping it DRY
You basically give each of your controllers a "type". Being logged in could be a criteria of one of your base controllers, which saves you trying to directly access any of your controllers which is bad mojo.
You can try creating a form on the index page and submit it to index.php/login/. This way you won't need two entry points.
Just do the same as you have done for the login View, specify the same action attribute of the form to the index View, and it will be sent to the same login controller with no need to create the two login controllers. You might want to append a query string in the action attribute of the form to distinguish from which View the request has come.