I know there's the usual way to render CSRF token hidden input with form_rest, but is there a way to render just CSRF input itself? I've overridden {% block field_widget %} in theme to render a piece of additional text. But as CSRF token is rendered in input field too and I got a piece of text I don't need next to a hidden field. So I'd like to render it separately with an argument that tells it not to render this text.
you can do it with {{ form_widget(formView._token) }}
If you have formView object, you can render it using Twig function:
{{ form_widget(formView._token) }}
If you haven't - you can render token without using form object directly:
<input type="hidden" name="token" value="{{ csrf_token('some-name') }}">
Works in Symfony 2.x and 3.x
To validate the token you can use the following code in your controller (Symfony 3.x):
$submittedToken = $request->request->get('token');
if ($this->isCsrfTokenValid('some-name', $submittedToken)) {
// ... do something,
}
Or you can just simply use this :
{{ form_row(form._token) }}
This will automatically generate the proper hidden HTML elements, ie the proper HTML structure and field names, according to the type of form you're using.
I needed to render the csrf input inside Twig so that I could use it for Delete operations.
Using {{ csrf_token('authenticate') }} as per #YuryPliashkou's answer gives me the incorrect token (one which is only valid for logins!)
What worked for me was this {{ csrf_token('form') }} which gives me the correct csrf token which I would then pass to my controller via ajax.
<span id="csrf_token" data-token="{{ csrf_token('form') }}"></span>
// my ajax call
$.ajax({
url: localhost/admin/product/4545, // 4545->id of the item to be deleted
type: 'POST',
data: {
"_method": "DELETE",
"form[_token]": $("#csrf_token").data("token") // passed csrf token here
},
success: function(result) {
// Do something
}
});
Verified its working on Symfony 3.x.
Reference
didn't find solution worked for me, finded and tested and worked for my Simfony3 value="{{ _token }}" in example
<form name="form" method="post" action="{{ path('blog_show', { 'id': blog.id }) }}">
<input name="_method" value="DELETE" type="hidden">
<input class="btn btn-danger" value="Delete" type="submit">
<input id="form__token" name="form[_token]" value="{{ _token }}" type="hidden">
</form>
more about scrf can be viewed here: Creating forms manually in Symfony2, but still use its CSRF and isValid() functionalily
Related
I'm in the process of making a Bootstrap 4 styled payment form for my app, wherein radio buttons select the payment method. In attempting to make my form via Symfony's form classes, I've found them to be too restrictive/clumsy to do what I want. I DO NOT want to mess around with Symfony form theming (I find it annoyingly verbose), I DO NOT want to use Symfony's pre-made Bootstrap theme, and I DO NOT want to use any createFormBuilder anything.
So, is there a way for me to make a plain old HTML form, but with Symfony's CSRF token? This answer seems promising, but doesn't mention CSRF protection.
According to this documentation How to Implement CSRF Protection ,
an attempt of solution is to use something like (in symfony 3.4 and 4) :
in your controller, you can have something like :
/**
* #Route("/names", methods={"POST"}, name="app_post_names")
*/
public function postName(Request $request)
{
$name = $request->request->get('name');
$csrfToken = $request->request->get('_csrf_token');
if(!$this->isCsrfTokenValid('token_id', $csrfToken)) {
// ... throw bad request
}
// ... Do other thing
}
Now in your template you can have something like (with your own design) :
<form action="{{ path('app_post_names') }}" method="post">
Name : <input name="name" type="text" />
<input name="_csrf_token" value="{{ csrf_token('token_id') }}" type="hidden" />
<input type="submit" value="send" />
</form>
Don't use Symfony at all, and generate your own token?
You don't really need to use Symfony form theming when making a form. Myself, I always build my own form tags.
You want to customise your select? Can be done too
You want to use fields which aren't in an entity, can be done as well...
Symfony forms aren't as restrictive as you think.
You most likely don't have the "know how" about this matter.
Controller
public function customFormAction(Request $request) {
$form=$this->createFormBuilder()
->setAction($this->generateUrl('route_name'))
->setMethod('POST')
->add("customField", ChoiceType::class, array(
'choices'=>array(
'1'=>'Choice 1',
'2'=>'Choice 2',
'3'=>'Choice 2',
),
'required'=>true,
'mapped'=>false, //Isn't mapped to any entity
))
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$customField=$form->get('customField')->getData();
//do your stuff
}
return $this->render('route_name', array(
'form'=>$form->createView(),
));
}
Twig view
<form action="{{ form.vars.action }}" method="{{ form.vars.method }}">
<div class="input-field">
<select id="{{ form.customField.vars.id }}" name="{{ form.customField.vars.full_name }}" class="my_classes">
{% for option in form.customField.vars.choices %}
<option data-attr="my_attributes" value="{{ option.value }}">{{ option.label }}</option>
{% endfor %}
</select>
</div>
<input name="{{ form._token.vars.full_name }}" value="{{ form._token.vars.value }}" type="hidden">
</form>
With this, I'm barely using any twig templating, I still have a CSRF token and Symfony barely handle the form (it will only check CSRF token)
I am working on a Laravel 5.4 application in which I want to enable the user to delete certain images which they have uploaded. The images have a small x on the right top which makes a modal pop up. I added a partial code of the modal form. When I want to submit the destroy option I get the error:
(1/1) MethodNotAllowedHttpException
in RouteCollection.php (line 251)
Could someone help me explain what I am doing wrong. I have tried changing the method in the form to DELETE and changed the route file to get, post, any etc.
Modal popup:
<a data-toggle="modal" data-target="#destroyModel" data-route="{{ route('client.progress.destroy', [$progressPicture]) }}" data-name="{{ $progressPicture->original_file }}" data-value="{{ $progressPicture->id }}">
<span class="close">×</span>
</a>
Modal form:
<form method="POST" action="#" accept-charset="UTF-8">
<input name="_method" type="hidden" value="delete">
<input type="hidden" name="_token" value="ud9UPrV3tXJ0iuQ96TELClQUcTksKx3Bimv54h9Z">
<input name="id" type="hidden" value="">
<button type="button" class="btn btn-default" data-dismiss="modal">Annuleren</button>
<button type="submit" class="btn btn-danger"><i class="fa fa-lg fa-trash"></i> Verwijderen</button>
</form>
Route file
Route::post('destroy_progress', 'Client\PictureController#destroyProgress')->name('progress.destroy');
JS
<script type="text/javascript">
$(document).ready(function () {
$('#destroyModel').on('show.bs.modal', function (event) {
let button = $(event.relatedTarget);// Button that triggered the modal
let modal = $(this);
let original_file = button.data('original_file');
let title = ":original_file verwijderen?";
title = title.replace(":original_file", original_file);
let message = "Weet u heel zeker dat u :original_file wilt verwijderen?";
message = message.replace(":original_file", name);
modal.find('.modal-footer form').attr('action', button.data('route'));
modal.find('.modal-title').html(title);
modal.find('.modal-body').html(message);
modal.find('.modal-footer input[name=id]').val(button.data('id'));
});
});
</script>
HTML forms do not support PUT, PATCH or DELETE actions. So, when defining PUT, PATCH or DELETE routes that are called from an HTML form, you will need to add a hidden _method field to the form. The value sent with the _method field will be used as the HTTP request method:
<form action="/foo/bar" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
To generate the hidden input field _method, you may also use the method_field helper function:
<?php echo method_field('PUT'); ?>
You can also do it using laravel blade template as
{{ method_field('PUT') }}
Then create a route which accepts the PUT request as
Route::put('destroy_progress', 'Client\PictureController#destroyProgress')->name('progress.destroy');
may I suggest using Laravel Forms
here is the link https://laravelcollective.com/docs/5.4/html but instead of using composer require "laravelcollective/html":"^5.4.0" just use this composer require "laravelcollective/html" to get the latest version, because the latest version solved the syntactical errors, the most common was the token() method
I am learning Routing in Laravel 5.4 by viewing a tutorial created by DevDojo. Using the following codes in routes/web.php will emerge the TokenMismatchException error and my code does not work after I press the submit button:
Route::post('test', function () {
return 'Printed by the route responsible for test post action.';
});
Route::get('test', function () {
echo '<form method="post" action="test">';
echo '<input type="submit">';
echo '</form>';
});
I searched this same forum here and also the other places on the net like laravel.io or laracasts.com and everyone is talking about problems that occur when Laravel tries to detect the session of the request that is getting made.
I tried to fix the problem by adding the following lines to the Route::get rules but the issue does not get fixed:
echo '<input type="hidden" name="_method" value="post">';
echo '<input type="hidden" name="_token" value="csrf_field();">';
I hope you help me fix it by telling me how to properly use csrf_field(), csrf_token() or anything else needed here in the route file.
Thank you very much in advance.
csrf_token() just gives you the token.
csrf_field() builds the entire input field for you.
example:
{{ csrf_token() }} // Outputs: SomeRandomString
{{ csrf_field() }} // Outputs: <input type="hidden" name="_token" value="SomeRandomString">
in your question:
use
<input type="hidden" name="_token" value="csrf_token();">;
instead of
<input type="hidden" name="_token" value="csrf_field();">;
on the other hand
you could use
echo csrf_field();
OR
{{ csrf_field() }}
I think you're on the right track with the hidden inputs (if you've got a fresh Laravel install, otherwise make sure checking the token isn't disabled);
I recommend you use the (official) Form Builder for Laravel to handle forms (have a look here).
Afterwards, have a look here:
(1)
{{ Form::open(array('url' => 'profile')) }}
your form stuff goes here
{{ Form::close() }}
(2) Make sure to have this to output the token: echo Form::token(); (before you close the form)
(3) And finally, have a POST Route registered, that checks the token:
Route::post('profile', array('before' => 'csrf', function()
{
//
}));
Alternatively, you can specify form action directly to the function (my personal favorite):
echo Form::open(array('action' => 'Controller#method'))
I want to pass an input value from one blade file to another blade file.
I'm new to PHP Laravel, and I'm getting an error when attempting to use it.
I think my syntax is wrong here. Can somebody help?
channeling.blade:
<select class="form-control " name="fee" id ="fee"></select>
This is the link to the next page, where i want to send the value of "fee":
<input type="hidden" value="fee" name="fee" />
Click to Channel</p>
This is my web.php:
Route::post('pay', [
'as' => 'fee',
'uses' => 'channelController#displayForm'
]);
This my controller class:
public function displayForm()
{
$input = Input::get();
$fee = $input['fee'];
return view('pay', ['fee' => $fee]);
}
Error message:
Undefined variable: fee
(View: C:\xampp\htdocs\lara_test\resources\views\pay.blade.php)
pay.blade:
<h4>Your Channeling Fee Rs:"{{$fee}}"</h4>
You should use form to send post request, since a href will send get. So, remove the link and use form. If you use Laravel Collective, you can do this:
{!! Form::open(['url' => 'pay']) !!}
{!! Form::hidden('fee', 'fee') !!}
{!! Form::submit() !!}
{!! Form::close() !!}
You can value inside a controller or a view with request()->fee.
Or you can do this:
public function displayForm(Request $request)
{
return view('pay', ['fee' => $request->fee]);
}
I think you can try this, You mistaken url('pay ') with blank:
change your code:
Click to Channel</p>
to
Click to Channel</p>
Further your question require more correction so I think you need to review it first.
You can review about how to build a form with laravel 5.3. Hope this helps you.
You have to use form to post data and then you have to submit the form on click event
<form id="form" action="{{ url('pay') }}" method="POST" style="display: none;">
{{ csrf_field() }}
<input type="hidden" value="fee" name="fee" />
</form>
On the click event of <a>
<a href="{{ url('/pay') }}" onclick="event.preventDefault();
document.getElementById('form').submit();">
Logout
</a>
tl;dr: I believe #AlexeyMezenin's answer is the best help, so far.
Your current issues:
If you have decided to use Click to Channel, you should use Route::get(...). Use Route::post(...) for requests submitted by Forms.
There isn't an Input instance created. Input::get() needs a Form request to exist. Thus, the $fee an Undefined variable error message.
The value of <input type="hidden" value="fee" name="fee"/> is always going to be the string "fee". (Unless there's some magical spell casted by some JavaScript code).
The laravel docs suggest that you type-hint the Request class when accessing HTTP requests, so that the incoming request is automatically injected into your controller method. Now you can $request->fee. Awesome, right?
The way forward:
The BasicTaskList Laravel 5.2 tutorial kick-started my Laravel journey.
I changed the code like this and it worked..
echanneling.blade
<input type="hidden" value="fee" name="fee" />
<button type="submit" class="btn btn-submit">Submit</button>
channelController.php
public function about(Request $request)
{
$input = Input::get();
$fee = $input['fee'];
return view('pay')->with('fee',$fee);
}
Web.php
Route::post('/pay', 'channelController#about' );
I am trying to change the approach of rendering templates. I was using a server-side template engine. Now that I need to return only JSON from backend instead of HTML, I need to move my templating to front-end.
The problem for me as a newbie, is when the template contains a form. In other words, when the final JSON should also contain a csrf token. Please to take the example of CRUD application for books (one entity Book(id_book, name)). The template for Reading a record shows the book name and allow deletion of a book.
In Symfony2 controller, I use createFormBuilder() method that creates the delete form object, to which I apply createView()method. The object returned by the latter is used by form_widget()in the template engine (Twig). At the end:
<div id="bookName">{{book.name}}</div>
<div id="bookDelete">
<form action="{{ path('book_delete', { 'id': book.id }) }}" method="post">
<input type="hidden" name="_method" value="DELETE" />
{{ form_widget(delete_form) }}
<button type="submit"></button>
</form>
</div>
Which will return:
<div id="bookName">Symfony2 In Depth</div>
<div id="bookDelete">
<form action="/web/app_dev.php/deletes" method="post">
<input type="hidden" name="_method" value="DELETE">
<div id="form">
<input type="hidden" id="form_id" name="form[id]" value="15">
<input type="hidden" id="form__token" name="form[_token]" value="dd6573ae916ae30f78ba35a8c67e5d42a2764c1c">
</div>
<button type="submit"></button>
</form>
What I imagine when moving template rendering to front-end is a final JSON from server looking like:
{
'id':15,
'name': 'Symfony2 in Depth',
'csrf_token' : 'dd6573ae916ae30f78ba35a8c67e5d42a2764c1c'
}
Question is how to implement the same Symfony2 internal mechanism to render csrf token for DELETE form, as part of the final JSON to read a book entity? Is it acceptable to get rid of {{ form_widget(delete_form) }} and all its long objects, and only serialize csrf token with book name? What does this will affect? I feel it is good for performance but how?
Your usual guidance is much appreciated.
You can create you twig file something like:
{
'id': '{{ form.id.vars.value }}'
'name': '{{ form.name.vars.value }}'
'csrf_token': '{{ form._token.vars.value }}'
}
Anyway I dont recommend you use csrf token when you are using API, it is better if you disabled. If you want to disable for all application in the config.yml:
framework:
csrf_protection:
enabled: false
Or just for one form in the Type form add:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'csrf_protection' => false,
));
}