I am making an ajax request with Csrf component load in my AppController
However I get the error {"message":"CSRF token mismatch.","url":"\/module_slides\/loadDeck.json","code":403}
Here is the request header
POST /module_slides/loadDeck.json HTTP/1.1
Host: www.hotelieracademy.com
Connection: keep-alive
Content-Length: 18
Origin: https://www.hotelieracademy.com
X-XSRF-TOKEN: 3d3901b1de9c5182dce2877c9e1d9db36cdf46a6
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Referer: https://www.hotelieracademy.com/courses_employees/player/70
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: csrfToken=3d3901b1de9c5182dce2877c9e1d9db36cdf46a6; CAKEPHP=3n6lpi94hrdgsg8mv4fsnp1m30; _ga=GA1.2.2010364689.1424741587
My ajax code
$.ajax({
url: '/module_slides/loadDeck.json',
type: 'POST',
headers: { 'X-XSRF-TOKEN' : this.csrfToken },
beforeSend: function (xhr) {
xhr.setRequestHeader('X-CSRF-Token', this.csrfToken);
},
dataType: 'json',
data: {
I have left the beforeSend: as suggest by another post but does not seem to alter the header so I added headers:
I use a hidden input to get the CsfR token to use in my js code
<input id="csrfToken" type="hidden" value="<?= $this->request->getParam('_csrfToken') ?>">
I've met the same problem.
Probably, this is the answer to add "_csrfToken":"xxxxxxx" to data{}.
$.ajax({
url: '/module_slides/loadDeck.json',
type: 'POST',
headers: { 'X-XSRF-TOKEN' : this.csrfToken },
beforeSend: function (xhr) {
xhr.setRequestHeader('X-CSRF-Token', this.csrfToken);
},
dataType: 'json',
data: {
"_csrfToken":"3d3901b1de9c5182dce2877c9e1d9db36cdf46a6"
}
This is my blog.but it's Japanese Only.
http://www.tsuji75.com/?p=62
Here is my solution.
For the CSRF token, I am creating an empty cakephp form and it provides the CSRF token.
Also, I do not unlock any action. instead I do unlock fields.
Ref: https://book.cakephp.org/3.0/en/controllers/components/security.html
here is my working example.
Scenario: Ajax call to add an event was failing due to cakephp 3 CSRF token mismatch issue.
Solution:
I have created an empty form in the view so it can provide CSRF token for my form and then attached the required input fields before the ajax. In the form itself, I unlocked the hidden fields. This way I do not disturb CSRF component.
In VIEW
<?= $this->Form->create(false, [
'id' => "ajaxForm",
'url' => ['controller' => 'XYZ', 'action' => 'add'],
'class'=> "addUpdateDeleteEventForm"
] );
$eventdata = [];
?>
<?= $this->Form->unlockField('id'); ?>
<?= $this->Form->unlockField('start'); ?>
<?= $this->Form->unlockField('end'); ?>
<?= $this->Form->unlockField('title'); ?>
<?= $this->Form->button('Submit Form', ['type' => 'submit']);?>
<?= $this->Form->end(); ?>
Ajax:
var id = $("<input>")
.attr("type", "hidden")
.attr("name", "id").val(id);
var titleField = $("<input>")
.attr("type", "hidden")
.attr("name", "title").val(title);
var startTime = $("<input>")
.attr("type", "hidden")
.attr("name", "start").val(start);
var endTime = $("<input>")
.attr("type", "hidden")
.attr("name", "end").val(end);
$('#ajaxForm').append(id);
$('#ajaxForm').append(titleField);
$('#ajaxForm').append(startTime);
$('#ajaxForm').append(endTime);
var ajaxdata = $("#ajaxForm").serializeArray();
$.ajax({
url:$("#ajaxForm").attr("action"),
type:"POST",
data:ajaxdata,
dataType: "json",
success:function(response)
{
toastr.success(response.message, response.title);
calendar.fullCalendar("removeEvents");
calendar.fullCalendar("refetchEvents");
},
error: function(response)
{
toastr.error(response.message, response.title);
}
});
Hope this helps.
Related
I am building a web application, on the front end side I am using Nuxt js (Laravel sanctum package) and on the back end side I am using Laravel sanctum
I configure the front-end and back-end both, cookies are also generating correctly but I unable to hit the Laravel route. When I send the request it return 200 code with the cookie but Laravel method return nothing, it's means that my app is not hitting the Laravel method. After clicking on the login button I am redirected to the dashboard but console return no response with no error.
My login page headers
Request URL: http://localhost:3000/http://localhost:8000/api/admin/login
Request Method: POST
Status Code: 200 OK
Remote Address: 127.0.0.1:3000
Referrer Policy: strict-origin-when-cross-origin
Accept-Ranges: none
Connection: keep-alive
Content-Length: 2779
Content-Type: text/html; charset=utf-8
Date: Mon, 24 May 2021 16:08:05 GMT
ETag: "adb-BuJ98IeCR24JYV5bINxcPHcMBsc"
Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,la;q=0.8,mt;q=0.7,id;q=0.6,pl;q=0.5,fr;q=0.4
Connection: keep-alive
Content-Length: 2
Content-Type: application/json
Cookie: auth.strategy=laravelSanctum; auth._token_expiration.laravelSanctum=false; auth._token.laravelSanctum=false
Host: localhost:3000
Origin: http://localhost:3000
Referer: http://localhost:3000/admin/login
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36
X-Requested-With: XMLHttpRequest
Api.php
Route::prefix('admin')->group(function(){
Route::post('/login', [LoginController::class, 'login'])->name('admin.login');
});
LoginController.php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class LoginController extends Controller
{
public function login(Request $request)
{
return "Login Success";// Just for testing
}
}
nuxt.config.js
modules: [
'bootstrap-vue/nuxt',
'#nuxtjs/axios',
'#nuxtjs/auth-next'
],
auth: {
strategies: {
'laravelSanctum': {
provider: 'laravel/sanctum',
url: '/http://localhost:8000',
endpoints:{
login:{
url:'/api/admin/login',
withCredentials: true,
method: 'post',
},
logout:{
url:'admin/logout'
},
user:{
url:'/user'
},
},
user:{
property:Array
}
},
},
redirect:{
login: '/admin/login',
logout: '/',
home: '/'
}
},
Login.vue
<template>
<div>
<index />
<b-container>
<b-row>
<b-col cols="*" sm="*" md="6" lg="6" class="mx-auto mt-5 offset-2">
<b-card title="Login Page">
<b-form>
<b-form-group>
<label for="text-email">Email</label>
<b-form-input type="email" v-model="form.email" aria-describedby="email-help-block"></b-form-input>
</b-form-group>
<b-form-group>
<label for="text-password">Password</label>
<b-form-input type="password" v-model="form.password" aria-describedby="password-help-block"></b-form-input>
</b-form-group>
<b-form-group>
<b-button type="submit" #click.prevent="login()" block variant="primary">Login</b-button>
</b-form-group>
</b-form>
</b-card>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script>
import index from '../index.vue'
export default {
components: { index },
data(){
return {
form:{
email: '',
password: '',
}
}
},
methods:{
async login(){
await this.$auth.loginWith('laravelSanctum', {
data: {
email: this.email,
password: this.password
}
})
.then( (response) => {
this.$router.push('/admin/dashboard')
console.log( response );
})
.catch( (error) => {
console.log( error );
})
}
}
}
</script>
package.json
"dependencies": {
"#nuxtjs/auth-next": "5.0.0-1620773067.c356fed",
"bootstrap": "^4.6.0",
"bootstrap-vue": "^2.21.2",
"core-js": "^3.9.1",
"nuxt": "^2.15.3"
},
My request URL is invalid, the spa domain added in the URL that's why my spa is not sending requests to the server.
Request URL: http://localhost:3000/http://localhost:8000/api/admin/login
TO
Request URL: http://localhost:8000/api/admin/login
That works fine.
Using Joomla:
My problem is when I submit the button, ajax send an empty data array back to my client. Debbuging in the console shows me that datas in the header but the preview and response values are empty.
Here is my code (I am using a modal form from bootstrap).
HTML in my default script:
<form action="<?php echo JRoute::_('index.php?option=com_addproduct&view=addproducts'); ?>" method="post" name="modalMessageForm" id="modalMessageForm" enctype="multipart/form-data">
<input type="file" id="message-image-upload" accept="image/*" style="display:none;" name="message-image-upload">
<textarea class="form-control message-textarea" id="message-textarea" placeholder="Nachricht..." name="new-message" rows="4"></textarea>
<button type="button" id="button-close-message" class="btn btn-default btn-block btn-message-close" style="display:none; margin-top:5px;"><?=JText::_( 'COM_ADDPRODUCT_MODAL_MESSAGES_CLOSE')?></button>
</form>
JQuery / Ajax:
$(document).on("submit", "#modalMessageForm", function(e)
{
var form = $('#modalMessageForm').get(0);
e.preventDefault();
var formData = new FormData(form);
for(var pair of formData.entries()) {
console.log(pair[0]+ ', '+ pair[1]);
}
$.ajax({
crossDomain: true,
type: "POST",
url: "index.php?option=com_addproduct&task=sendMessages&format=json",
data: formData,
dataType: "json",
processData: false
})
.done(function(data, textStatus, jqXHR){
console.log('Message: '+data.new-message+' PicName: '+data.img);
})
});
Here my controller.php:
public function sendMessages()
{
JResponse::setHeader('Content-Type', 'application/json', true);
$app = JFactory::getApplication();
$input = $app->input;
$new-message = $input->getString('new-message', '', 'RAW');
$img = $_FILES['message-image-upload']["name"];
$img = JFile::makeSafe($img);
$results=array(
'new-message' => 'new-message',
'img' => $img
);
echo json_encode($results);
$app->close();
}
I got the datas / variables in the console log.
it is:
new-message: null,
img: null
trying to set contentType: false will give me an 500 error.
Thank you very much
That´s the info from my network
enter image description here
I figure something out.
It´s the URL in my ajax command.
When I am using a normal url like
url: 'upload.php'
that will work and then I can set the
contentType: false,
But this is not safety enought.
I just want to use this url
url: "index.php?option=com_addproduct&task=sendMessages&format=json",
But then I got the error message that the view is not found. That´s very strange.
$('#id').change(function(){
var a = $('#id_one').val();
var token = '<?php echo csrf_token(); ?>';
$.ajax({
url: "url",
type: 'POST',
data: {'id':a,'_token':token},
success: function(data)
{
// some code
}
});
})
This is my code.
Getting token mismatch error..!!
I have tried both of the following..
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<script type="text/javascript">
var _globalObj = {{ json_encode(array('_token'=> csrf_token())) }}
Can any one help ??
You can utilize your token from the blade template, just declare your session token in the blade file of your view under the script tag like this:
<script> var token = '{{ Session::token() }}'; </script>
and call the token in ajax, in your code it will be something like this:
$('#id').change(function(){
var a = $('#id_one').val();
$.ajax({
url: "url",
type: 'POST',
data: {'id':a,'_token':token},
success: function(data)
{
// some code
}
});
})
Possibly because the token field name should be _token and not token
Also If this javascript code in a separate javascript file then php function will not work.
Also if the data you are trying to send is of a form then you can do this
$('#id').change(function(){
var data = $("#form").serialize() ;
$.ajax({
url: "url",
type: 'POST',
data: data,
success: function(data)
{
// some code
}
});
})
where your form looks like
<form id="form">
<input type='hidden' value='{{ csrf_token() }}' name='_token'>
<input type="text" name='id'>
</form>
$.ajax({
url: someurl,
type: 'POST',
data : formData,
headers: {
"x-csrf-token": $("#token").data('id')
}
});
}
and in your html
<div id="token" data-id="{!! csrf_token() !!}"></div>
i have a form with method=post.In that form i have an image upload field which is ajax.when the ajax call process,verify csrf token mismatch error occure.help me.this is my code..,
<script>
$(document).ready(function(){
$(document).on("click", "#upload", function() {
var file_data = $("#groupe_img").prop("files")[0]; // Getting the properties of file from file field
var form_data = new FormData(); // Creating object of FormData class
form_data.append("file", file_data) // Appending parameter named file with properties of file_field to form_data
form_data.append("csrftoken",document.mainform.csrftoken.value;) // Adding extra parameters to form_data
$.ajax({
url: "/upload_avatar",
dataType: 'script',
cache: false,
contentType: false,
processData: false,
data: form_data, // Setting the data attribute of ajax with file_data
type: 'post'
})
})
});
</script>
this is my html portion
<input type="file" name="groupe_img" id="groupe_img">
<button id="upload" value="Upload">upload image</button>
tysm
First add csrf token to a meta tag like this (in main layout for example: resources/views/default.blade.php in head section):
<meta name="_token" content="{{ csrf_token() }}"/>
Then use $.ajaxSetup before ajax call:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
}
});
$.ajax({
url: "/upload_avatar",
dataType: 'script',
cache: false,
contentType: false,
processData: false,
data: form_data,
type: 'post'
})
I'm still using Laravel 4.2 and I'm trying to post a form with AJAX, but it gives me error 404 for a post page. Here is my code:
routes.php:
Route::post('/', array(
'as' => 'postFora',
'uses' => 'HomeController#postFora'
));
HomeController.php:
public function postFora() {
$form = Input::all();
$f = New Fora;
$f->content = Input::get('contant');
$f->user_id = Input::get('user_id');
$f->save();
return Response::json(array('success' => true));
}
main.js:
$('.dodaj-foro').submit(function(e) {
var form = $(this);
$.ajax({
url : "http://localhost/belezka/",
type: "POST",
dataType: "JSON",
data: form.serialize(),
success: function (data) {
alert('ok');
}
});
e.preventDefault();
});
index:
<form class="dodaj-foro" action="/" method="post" accept-charset="utf-8">
<input type="hidden" name="user_id" value="{{$user[0]->id}}">
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
<input type="text" name="contant" placeholder="Fora tuki">
</form>
I think you have to enter the route in present in Route file instead of http://localhost/belezka/
Try to replace :
$.ajax({
url : "http://localhost/belezka/",
type: "POST",
dataType: "JSON",
.....
By :
$.ajax({
url : "postFora",
type: "POST",
dataType: "JSON",
.....
Hope this will help.
In case you did not change the defaults Laravel comes with, add public to the AJAX request URL. By default, the route '/' corresponds to http://localhost/belezka/public/ due to URL rewriting.