This is driving me crazy. I'm getting token mismatches on each POST whether from a Laravel form or from AJAX. I added some code to the filter to show me the session vs. _token:
Route::filter('csrf', function()
{
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
$token = Input::has('_token') ? Input::get('_token') : '';
$sessionToken = Session::token();
if ($sessionToken != $token)
{
$message = 'Token mismatch';
// This one is for debug purposes only
return Response::json(['flash' => "$message; session: $sessionToken ; yours : $token"], 401);
return Response::json(['flash' => $message], 401);
}
}
});
Here's the login form:
{{ Form::open(array('route' => 'sessions.store')) }}
<div class="form-group">
{{ Form::label('email', 'Email Address') }}
{{ Form::text('email', '', array('placeholder' => 'example#gmail.com', 'class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('password', 'Password') }}
{{ Form::password('password', array('placeholder' => 'Enter your password', 'class'=>'form-control')) }}
</div>
<div class="form-group">
{{ Form::submit('Sign in', array('class' => 'btn login'))}}
Create an Account
</div>
{{ Form::close() }}
For example when logging in, here is the token mismatch flash I get:
{"flash":"Token mismatch; session: uN3sd8PNWUfgTuqc1RZrRfXgpGpHOEKkCtoo3XVX ; yours : Ybmn6u80rLpxIcGdahd7KT2eR6WmcaPN28arZ9kg"}
It's happening when I have app/config/session.php set to 'apc'. All is fine when it's set to 'native' or 'cookie'. I have cache set to 'apc', which is our caching engine on our server.
Ideas?
You are not submitting _token with your POST request.
Add
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>"
before {{Form::close()}}
http://laravel.com/docs/security#protecting-routes
Are your sessions being saved to the DB? In my case they weren't.
AndreasLutro from the #laravel IRC suggested to check this issue out! https://github.com/laravel/framework/issues/4441
I had that problem too, I don't know the actual way to fix this. I think this is a bug, but I needed my application to function. So here's the original app/filter.php file:
Route::filter('csrf', function() {
if (Session::token() != Input::get('_token'))
throw new Illuminate\Session\TokenMismatchException;
}
});
I modified it to use the csrf_token() function and it worked for me,
Route::filter('csrf', function() {
if (csrf_token() != Input::get('_token')) {
throw new Illuminate\Session\TokenMismatchException;
}
});
This is just a quick fix to get my application up and working before someone figures out a solution.
I ran into this issue on my local computer. I have Laravel running on a web server and the csrf token is working great, but not on my local computer.
I have cache set to file on my local computer.
I found out that sessions were not getting saved. I fixed this by changing the permissions for the "storage/sessions" folder on my local machine (not the server!) to 777.
Related
here you can see my form where I put in a username and have a hidden idgroup field.
{!! Form::open(array('route'=>'create.invitation')) !!}
<div class="form-group">
{{Form::label('username', 'Username')}}
{{Form::text('username', '', ['class' => 'form-control', 'placeholder' => 'Enter Username'])}}
<input type="hidden" name="idgroup" value="{{$group}}"/>
{{ csrf_field() }}
</div>
<div>
{{Form::submit('Submit',['class' => 'btn btn-primary'])}}
<a class="btn btn-default btn-close" href="{{ route('home') }}">Cancel</a>
</div>
{!! Form::close() !!}
After that this route leads me to my controller function
Route::post('invitation/show', 'InvitationController#create')->name('create.invitation');
How can I add the username and the idgroup to my url?
My problem is now when I click submit I get back this url http://127.0.0.1:8000/invitation/create and when I click enter to the url line I get an error no message because no parameter will pass to the function.
Add. Here is the function
public function create(Request $request)
{
$request->validate([
'username' => [
'required', 'alpha_num', new ExistingUser, new UserNotAdmin
]
]);
$username = $request->username;
$iduser = User::where('name', $username)->select('id')->first();
$group = $request->idgroup;
return view('invitation.overview')->with('group', $group)->with('iduser', $iduser);
}
You cannot pass parameter inside POST body without submitting a form.
But you can try to allow both GET or POST by using any() for the route, so you can test the page around.
Route::any('invitation/show', 'InvitationController#create')->name('create.invitation');
And then, you can try pass variable through queries inside URL
http://127.0.0.1:8000/invitation/create?username=something&idgroup=1
I have a regular form with a single input:
{{ Form::open(array('id' => 'form_search')) }}
<div class="form-group">
{{ Form::text('search', '', array('class' => 'form-control', 'placeholder' => 'Search...')) }}
</div>
{{ Form::close() }}
When the form is submitted, I want it to redirect to a page showing the results by the following URL:
http://www.website.com/search/<QUERY_HERE>
For example, if someone typed john in the form input and submitted the form, the URL redirected to would look like:
http://www.website.com/search/john
How can I do this?
In your routes.php
//Handle form submit
Route::get('search', 'YourSearchController#yourSearchFunction');
//Return results
Route::get('search/{search}', 'YourSearchController#yourSearchResults');
Then add the route to your form:
{{Form::open(['route' => 'search'])}}
Then in yourSearchController:
function yourSearchFunction() {
$search = Input::only(['search']);
return Redirect::to('search/'.$search);
}
Then also in yourSearchController:
function yourSearchResults($search) {
return View::make('results')->with(compact('search'));
}
I have a CRUD for Users in Laravel 4.1
When the user want see his data, the url is: mydomain.com/public/users/3 (the show method).
How I can hide the id "3" in the url? So, if the number is visible, the user can see the data of other users (as 4,5 or others id)?
Thanks
In my filter.php I have:
Route::group(array('before' => 'auth'), function()
{
Route::resource('users', 'UserController');
});
Finally solved.
In UserController.php:
public function show()
{
//
$usuario = Auth::user();
// show the view and pass the nerd to it
return View::make('users.show')
->with('elusuario', $usuario);
}
In show.blade.php
#extends ("layout/layout")
#section ("principal")
<div class="form-group">
{{ Form::label('nombre', 'Nombre') }}
{{ Form::text('nombre',null, array('class' => 'form-control','placeholder'=>$elusuario->nombre,'disabled'=>'disabled')) }}
</div>
<div class="form-group">
{{ Form::label('email', 'Email') }}
{{ Form::email('email',null, array('class' => 'form-control','placeholder'=>$elusuario->email,'disabled'=>'disabled')) }}
</div>
<a class="btn btn-success" href="{{ URL::to('users/' . $elusuario->id . '/edit') }}">Modificar datos</a>
#stop
That solved the issue and the url don't show the id of user. Simply called as mydomain.com/public/users/perfil and has the data (id, name, etc) from session variable.
I want to create a route in laravel 4 with this parameters
$options = [ 'gs_bucket_name' => 'images_upload'];
$upload_url = CloudStorageTools::createUploadUrl('/upload_handler.php', $options);
which means a route that point to this $upload_url. createUploadUrl do a post at upload_handler.php and stores data to gs bucket. My problem is that post isn't performed because upload_url should be specified at routes. How can I do this?
upload_handler.php
<?php
var_dump($_FILES);
?>
view
{{ Form::open(array('action' => 'upload_handler','files' => true)) }}
{{ Form::file('file') }}
<br>
{{ Form::submit('Add Photo', array('class' => 'btn btn-primary' )) }}
{{ Form::close() }}
route
Route::group(array('before' => 'auth'), function() {
Route::post('upload_handler', function($upload_url = null) {
$options = [ 'gs_bucket_name' => 'images_upload'];
$upload_url = CloudStorageTools::createUploadUrl('/upload_handler.php', $options);
return $upload_url;
});
});
but this just returns the url. How to do post?
In pure php the code is:
require_once 'google/appengine/api/cloud_storage/CloudStorageTools.php';
use google\appengine\api\cloud_storage\CloudStorageTools;
$options = [ 'gs_bucket_name' => 'images_upload'];
$upload_url = CloudStorageTools::createUploadUrl('/upload_handler.php', $options);
?>
<div class="body">
<form action="<?php echo $upload_url ?>" enctype="multipart/form-data" method="post">
<input type="file" name="uploaded_files" size="40">
<input type="submit" value="Send">
</form>
</div>
Your question is a little vague I'm afraid but I think what you're after is Redirect::to. This will allow you to redirect the post request to the URL generated by the method on the CloudStorageTools class.
return Redirect::to($upload_url);
One of the coolest Laravel feature is, Laravel pre-filled the form fields if validation error occurred. However, if a page contain more than one form, and form fields have same name, Laravel pre-filling all forms fields.
For example:
I have a page where i have two forms to create new users or whatever.
<h1>Create user1</h2>
{{ Form::open(array('url' => 'foo/bar')) }}
{{ Form::text('name', null) }}
{{ Form::email('email', null) }}
{{ Form::close() }}
</h1>Create user2</h1>
{{ Form::open(array('url' => 'foo/bar')) }}
{{ Form::text('name', null) }}
{{ Form::email('email', null) }}
{{ Form::close() }}
Controller
class UsersController extends BaseController
{
public function store()
{
$rules = [
'name' => 'required',
'email' => 'required'
];
$validation = Validator::make(Input::all(), $rules);
if ($validation->fails()) {
return Redirect::back()->withInput()->withErrors($validation);
}
}
}
As i didn't fill up the email, Laravel will throw validation error and pre-filling the forms as following:
How to tell Laravel that do not fill-up the second form?
There's no Laravel way of doing this, but you can use HTML basic form arrays to make it work. You need to understand that you have to identify your forms and fields so Laravel knows exactly where the data came from and where to send it back to. If all your fields have the same name how could it possibly know?
This is a proof of concept that will work straight from your routes.php file.
As I did it all and tested here before posting the answer I used Route::get() and Route::post(), to not have to create a controller and a view just to test something I will not use. While developing this you will have to put this logic in a controller and in a view, where I think they are alredy in.
To test it the way it is, you just have to point your browser to the following routes:
http://yourserver/form
and when you push a button it will automatically POST tho the route:
http://yourserver/post
I'm basically giving all forms a number and giving the buttons the number that we will usin in Laravel to get the form data and validate it.
Route::get('form', function()
{
return Form::open(array('url' => URL::to('post'))).
Form::text('form[1][name]', null).
Form::email('form[1][email]', null).
'<button type="submit" name="button" value="1">submit</button>'.
Form::close().
Form::open(array('url' => URL::to('post'))).
Form::text('form[2][name]', null).
Form::email('form[2][email]', null).
'<button type="submit" name="button" value="2">submit</button>'.
Form::close();
});
And here we get the data, select the form and pass all of it to the validator:
Route::post('post', function()
{
$input = Input::all();
$rules = [
'name' => 'required',
'email' => 'required'
];
$validation = Validator::make($input['form'][$input['button']], $rules);
return Redirect::back()->withInput();
});
This is how you use it in a Blade view, now using 3 forms instead of 2 and you can have as many forms as you need:
<h1>Create user1</h2>
{{ Form::open(array('url' => URL::to('post'))) }}
{{ Form::text('form[1][name]', null) }}
{{ Form::email('form[1][email]', null) }}
<button type="submit" name="button" value="1">submit</button>
{{ Form::close() }}
</h1>Create user2</h1>
{{ Form::open(array('url' => URL::to('post'))) }}
{{ Form::text('form[2][name]', null) }}
{{ Form::email('form[2][email]', null) }}
<button type="submit" name="button" value="2">submit</button>
{{ Form::close() }}
</h1>Create user3</h1>
{{ Form::open(array('url' => URL::to('post'))) }}
{{ Form::text('form[3][name]', null) }}
{{ Form::email('form[3][email]', null) }}
<button type="submit" name="button" value="3">submit</button>
{{ Form::close() }}
And you can even use a loop to create 100 forms in blade:
#for ($i=1; $i <= 100; $i++)
User {{$i}}
{{ Form::open(array('url' => URL::to('post'))) }}
{{ Form::text("form[$i][name]", null) }}
{{ Form::email("form[$i][email]", null) }}
<button type="submit" name="button" value="{{$i}}">submit</button>
{{ Form::close() }}
#endfor
Use old input with $request->flash().
https://laravel.com/docs/5.2/requests#old-input