How to Pass CSRF token with AJAX request Laravel + Vue.js - ajax

I have a Vue.js component...
<template>
<form method="POST" action="/login">
<button class="btn btn-primary center-block" #click="$emit('buttonClicked')">
Login
</button>
</form>
</template>
<script>
var axios = require('axios');
Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('#token').getAttribute('content');
export default {
created: function () {
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
},
props: ['show'],
name: "login-component",
methods: {
close: function () {
this.$emit('close');
},
buttonClicked: function () {
axios.post('/login', {data: this.data})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error.message);
});
}
}
}
</script>
My csrf exists in meta:
<meta id="token" name="csrf-token" content="{{ csrf_token() }}">
But it doesn't pass with the Ajax request instead I get...
419 unknown status and no _token in console->Form Data
What am I doing wrong?
I tried to use...
window.axios.defaults.headers.common = {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN' : document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
};
But it didn't help.

I solved by this way:
export default {
data() {
return {
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content')
}
},
...
And inside <form></form>:
<input type="hidden" name="_token" :value="csrf">

Related

Laravel API: "POST http://localhost/api/post 419 (unknown status)" (Vue.js)

Im trying to make a post in a vue component with Laravel Api.
I got CSRF token in my welcome.blade.php:
<meta name="csrf-token" content="{{ csrf_token() }}">
Page does not refresh or add anything when i click on the button.
If i click on the button i get this in my console:
POST http://localhost/api/post 419 (unknown status)
PostList.vue
<template>
<div class="container py-4">
<form enctype="multipart/form-data" method="post" action="" #submit.prevent="addPost">
<input type="hidden" name="_token" value=""/>
<div class="modal-header">
<h4 class="modal-title">Create Post</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Title</label>
<input type="text" class="form-control" placeholder="Title" v-model="post.title">
</div>
<div class="form-group">
<label>Description</label>
<textarea class="form-control" placeholder="Body" v-model="post.body"></textarea>
</div>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-default" data-dismiss="modal" value="Cancel">
<input type="submit" class="btn btn-primary" value="Add">
</div>
</form>
</div>
</template>
<script>
export default {
data() {
return {
post: {
id: '',
title: '',
body: ''
}
};
},
created() {
this.getPosts();
},
methods: {
addPost(){
fetch('api/post', {
method: 'post',
body: JSON.stringify(this.post),
headers: {
'content-type': 'apllication/json'
}
})
.then(response => response.json())
.then(data => {
this.getPosts();
})
.catch(err => console.log(err));
}
}
};
</script>
PostController.php
public function store_vue(Request $request){
$post = new Posts();
$post->title = $request->get('title');
$post->body = $request->get('body');
$post->slug = Str::slug($post->title);
$post->author_id = $request->user()->id;
if ($post->save()) {
return new PostResource($post);
}
}
You are getting a 419 error because the request is missing the CSRF token.
You can add it to your form and see if it works for you
<form enctype="multipart/form-data" method="post" action="" #submit.prevent="addPost">
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
OR
Add the header with the CSRF to your call
<script>
export default {
data() {
return {
post: {
id: '',
title: '',
body: ''
}
};
},
created() {
this.getPosts();
},
methods: {
addPost(){
fetch('api/post', {
method: 'post',
body: JSON.stringify(this.post),
headers: {
'content-type': 'apllication/json',
'X-CSRF-TOKEN': document.querySelector("meta[property='csrf-token']").getAttribute("content");
}
})
.then(response => response.json())
.then(data => {
this.getPosts();
})
.catch(err => console.log(err));
}
}
};
</script>
Laravel has a middleware called VerifyCsrfToken which is enabled by default. It makes sure all POST requests have a csrf token. This tokens make sure the request is sent from our app only and not from any 3rd party scraper or form submiting tool.
When controller does not get _token in request, it throws error.
Add this 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
on header section in like belwo
You can try this
<script>
export default {
data() {
return {
post: {
id: '',
title: '',
body: ''
}
};
},
created() {
this.getPosts();
},
methods: {
addPost(){
fetch('api/post', {
method: 'post',
body: JSON.stringify(this.post),
headers: {
'content-type': 'apllication/json',
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
})
.then(response => response.text())
.then(data => {
this.getPosts();
})
.catch(err => console.log(err));
}
}
};
</script>

How to upload image using ajax in laravel

I have a trouble when to upload img using ajax in laravel. I have an error in getClientOriginalExtension() I think that trouble in enctype in ajax because the controller can not read the upload file.
this is my view :
<form name="data-form" id="data-form" enctype="multipart/form-data">
{{ csrf_field() }}
<input type="file" name="img_thumbnail" class="form-control">
</form>
<script type="text/javascript">
$(function () {
$.ajaxSetup({
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}
});
$('body').on('click', '#saveBtn', function(){
var url;
var registerForm = $("#data-form");
var formData = registerForm.serialize();
$(this).html('saving...');
$('#saveBtn').attr('disabled',true);
$.ajax({
enctype: 'multipart/form-data',
url: '{{ route('blog.store') }}',
type:'POST',
data:formData,
success:function(data) {
console.log(data);
if(data.errors) {
}
if(data.success) {
}
$('#saveBtn').html('Save Data');
$('#saveBtn').attr('disabled',false);
},
error: function (data) {
console.log('Error:', data);
$('#saveBtn').html('Save Data');
}
});
});
});
</script>
and this is my controller
$name_file = time().'.'.$request->img_thumbnail->getClientOriginalExtension();
$request->img_thumbnail->move(public_path('images'), $nama_file);
create.blade.php
#section('content')
<form id="submitform">
<div class="form-group">
<label for="name">Name</label>
<input type="text" name="name" id="name">
</div>
<div class="form-group">
<label for="photo">Photo</label>
<input type="file" name="photo" id="photo">
</div>
<button class="btn btn-primary" id="submitBtn" type="submit">
<span class="d-none spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
<span class="">Submit</span>
</button>
</form>
#endsection
#push('custom-scripts')
<script src="{{ asset('js/upload.js') }}"></script>
#endpush
upload.js
$(function () {
$('#submitBtn').on('click', (e) => {
e.preventDefault();
var formData = new FormData();
let name = $("input[name=name]").val();
let _token = $('meta[name="csrf-token"]').attr('content');
var photo = $('#photo').prop('files')[0];
formData.append('photo', photo);
formData.append('name', name);
$.ajax({
url: 'api/store',
type: 'POST',
contentType: 'multipart/form-data',
cache: false,
contentType: false,
processData: false,
data: formData,
success: (response) => {
// success
console.log(response);
},
error: (response) => {
console.log(response);
}
});
});
});
Controller
class MyController extends Controller
{
use StoreImageTrait;
public function store(Request $request)
{
$data = $request->all();
$data['photo'] = $this->verifyAndStoreImage($request, 'photo', 'students');
Student::create($data);
return response($data, 200);
}
}
StoreImageTrait
<?php
namespace App\Traits;
use Illuminate\Http\Request;
trait StoreImageTrait
{
public function verifyAndStoreImage(Request $request, $filename = 'image', $directory = 'unknown')
{
if ($request->hasFile($filename)) {
if (!$request->file($filename)->isValid()) {
flash('Invalid image')->error()->important();
return redirect()->back()->withInput();
}
return $request->file($filename)->store('image/' . $directory, 'public');
}
return null;
}
}
<form name="data-form" id="data-form" enctype="multipart/form-data">
{{ csrf_field() }}
<input type="file" name="img_thumbnail" class="form-control">
</form>
<script src=
"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<script type="text/javascript">
$(document).ready( function () {
$("form#data-form").on("submit",function (e) {
e.preventDefault();
var formData = new FormData(this);
//Ajax functionality here
$.ajax({
url : '{{route('blog.store')}}',
type : "post",
data : formData,
dataType : 'json',
success:function (data) {
console.log(data);
if(data.errors) {
}
if(data.success) {
}
$('#saveBtn').html('Save Data');
$('#saveBtn').attr('disabled',false);
}, // success end
contentType: false,
processData: false
}); // ajax end
}); // form submit end
}); //document end

Laravel ajax return 404

I'm trying to send data to back-end and i'm getting 404 error with this explanation in network tab:
"message": "",
"exception": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",
Route
Route::middleware('verified')->group(function () {
Route::post('/snaptoken/{id}', 'Admin\PayController#token')->name('securepaymentnow');
});
Controller
public function token(Request $request, $id)
{
//Find project
$project = Project::findOrFail($id);
//rest of data
}
Blade
//form and button
<form id="payment-form" method="POST" action="{{route('securepaymentnow', $project->id)}}">
#csrf
<input type="hidden" name="result_type" id="result-type" value="">
<input type="hidden" name="result_data" id="result-data" value="">
</form>
<button class="btn-sm bg-success pay-button" data-id="{{$project->id}}" type="submit"><i class="fas fa-fas fa-shield-alt"></i> Secure Payment</button>
//javascript
$('.pay-button').click(function (event) {
$.ajaxSetup({
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }
});
event.preventDefault();
// $(this).attr("disabled", "disabled");
var prdfoId = $(this).data('id');
$.ajax({
url: '{{url("/securepaymentnow")}}/'+encodeURI(prdfoId),
type: "POST",
cache: false,
success: function(data) {
var resultType = document.getElementById('result-type');
var resultData = document.getElementById('result-data');
}
});
});
Any idea?
.........................................................................................................................
if you are using url() function, you should use the {{ url('/snaptoken') }}.
But if you want to use the "name" from the "securepaymentnow", use route() function with this example {{ route('securepaymentnow', $theId) }}.
Both should works.
Refer Laravel NamedRoute for details.

Stripe-Vue payment POST 500 uncaught in promise

I think I messed something up with the csrf_field() but I did push the X-CSRF-TOKEN... I had a 419 error before but brought myself more into trouble...
The error
- POST /betaling 500
- Uncaught (in promise) Response {url: "/betaling", ok: false, status: 500, statusText: "Internal Server Error", headers: Headers
Header
<script>
var Cityofcompanies = {
csrfToken: "{{ csrf_token() }}",
stripeKey: "{{ config('services.stripe.key') }}"
};
Routes
Route::post('betaling', 'PaymentController#store')->name('payment');
App.js
window.Vue = require('vue');
require('vue-resource');
Vue.http.interceptors.push((request, next) => {
request.headers.set('X-CSRF-TOKEN', Cityofcompanies.csrfToken);
next();
});
Vue.component('CheckoutForm',
require('./components/CheckoutForm.vue'));
CheckoutForm.vue
<template>
<form action="/betaling" method="POST">
<input type="hidden" name="stripeToken" v-model="stripeToken">
<input type="hidden" name="stripeEmail" v-model="stripeEmail">
<button type="submit" #click.prevent="buy">Abonneer</button>
</form>
</template>
<script>
export default {
data() {
return {
stripeEmail: '',
stripeToken: ''
};
},
created() {
this.stripe = StripeCheckout.configure({
key: Cityofcompanies.stripeKey,
image:"https://stripe.com/img/documentation/checkout/marketplace.png",
locale: "auto",
currency: "eur",
token: (token) => {
this.stripeToken = token.id;
this.stripeEmail = token.email;
this.$http.post('/betaling', this.$data);
//.then(response => alert('Bedankt voor het abonneren!'));
}
});
},
methods: {
buy() {
this.stripe.open({
name: "Abonneer voor 1 jaar",
description: "Professional Version",
amount: 5000,
});
}
}
}
</script>
Show.blade.php
<div id="checkout">
<checkout-form></checkout-form>
</div>
<script>
window.onload = function () {
const app = new Vue({
el: '#checkout'
});
}
</script>
<script src="https://checkout.stripe.com/checkout.js"></script>
You'll need to look at the logs for the /betaling endpoint to see what the error might be here.

Laravel live ajax search - token mismatch

I am making a live search where user can search for business.
This would be done using ajax and display results however I get an error that there is an TokenMismatchException.
Here's my code:
Ajax:
function search_data(search_value) {
$.ajax({
url: '/searching/' + search_value,
method: 'POST',
headers: {
'X-CSRFToken': $('meta[name="token"]').attr('content')
}
}).done(function(response){
$('#results').html(response); // put the returning html in the 'results' div
});
}
Controller:
public function search($search) {
$search_text = $search;
if ($search_text==NULL) {
$data= Business::all();
} else {
$data=Business::where('name','LIKE', '%'.$search_text.'%')->get();
}
return view('results')->with('results',$data);
}
}
Route::
Route::get('/', function () {
return view('auth/login');
});
Route::group(['middleware' => ['auth']], function () {
Route::get('tfgm', 'GuzzleController#tfgm')->name('tfgm');;
Route::get('odeon', 'GuzzleController#odeon')->name('odeon');;
Route::get('chronicle', 'GuzzleController#oldham_chronicle')->name('chronicle');;
Route::get('smokeyard', 'GuzzleController#smokeyard')->name('smokeyard');;
Route::get('profile/', 'ProfileController#checkid')->name('profile');;
Route::get('create/business', 'BusinessController#addBusiness')->name('createBusiness');
Route::get('business/list', 'BusinessController#viewBusiness')->name('viewBusiness');
Route::get('business/{id}', 'BusinessController#displayBusiness')->name('displayBusiness');
Route::post('/searching/{search}', 'SearchController#search');
Route::post('update', 'ProfileController#updateProfile');
Route::post('create', 'BusinessController#createBusiness');
Route::post('image', 'ImageController#image');
Route::post('test2', 'ImageController#gallery');
Route::post('markers', 'BusinessController#saveMarkers');
Route::post('reviews', 'BusinessController#saveReviews');
});
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::get('/redirect/{provider}', 'SocialAuthController#redirect');
Route::get('/callback/{provider}', 'SocialAuthController#callback');
master.blade.php
<head>
<meta name="csrf-token" content="{{ csrf_token() }}" />
</head>
<form action="/search" method="get" autocomplete="off" class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" id="search_text" onkeyup="search_data(this.value, 'result');" placeholder="Search">
</div>
<div id="result">
#include('results')
</div>
</div>
</form>
Your line must be
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
In your ajax code you have written X-CSRFToken that is wrong. Correct is X-CSRF-TOKEN
Always use below code in you script file
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Change X-CSRFToken to X-CSRF-TOKEN

Resources