I am using angular wrapper for dropzone.js taken from this http://www.cantangosolutions.com/blog/Easy-File-Upload-Using-DropzoneJS-AngularJs-And-Spring
example.
What is the way to add csrf-token in angular dropzone.js?
Thanks,
This worked for me:
dropzone.on("sending", function(file, xhr, data) {
var csrftoken = $cookies.get('XSRF-TOKEN');
data.append('_csrf', csrftoken);
};
Related
i'm trying to get my post request running in vue.
I'm using vue-resource to do post/get requests. Get method is working. Post is not.
I used the vue-resource "get" for a pagination on my laravel program and it worked perfect.
Now I need to pass some data via post to my server, but this doesn't really work.
My app.js:
// require('./bootstrap');
window.Vue = require('vue');
import VueResource from 'vue-resource';
Vue.use(VueResource);
Vue.component('example-component', require('./components/ExampleComponent.vue'));
Vue.component('prices', require('./components/prices.vue'));
const app = new Vue({
el: '#app'
});
The important part of my component, where i'm trying to do the post request:
saveSellAndBuy: function () {
Vue.http.post('/dashboard/savePricingData', {
buyAP: this.buyAP,
sellAP: this.sellAP,
tradeID: this.currentEditedKey
}).then(function (data) {
console.log(data);
});
}
What I get:
app.js:13790 POST http://unicorn.com/dashboard/savePricingData 419 (unknown status)
Some exceptions of laravel with no message
exception: "Symfony\Component\HttpKernel\Exception\HttpException"
file: "/var/www/unicorn.de/htdocs/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php"
line: 203
message: ""
And yeah.. I have no clue anymore. Other people with the same or related problem said I need this in my head:
<meta name="csrf-token" content="{{ csrf_token() }}">
and this at the end ( this gets rendered after the vue instance )
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Of course I had those at the right place. I also tried to put this snipped here:
Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('#token').getAttribute('content');
At the end of my app.js file and it did not worked out for me. If I put this code over the const app and not at the end, my whole vueJS is not running anymore.
And here a picture that shows, that I do have the right cookies like XHR
Okay, I've found a way. I haven't thought that this will work. In the Laravel VerifyCsrfToken.php is a :
protected $except = [
'/dashboard/saveTradingData'
];
Where I can add URIs that should be excluded from CSRF verification.
But I don't really like this solution..
You can set the headers of any requests going out for vue-resource using interceptors:
Vue.http.interceptors.push((request, next) => {
const token = document.querySelector('#token').getAttribute('content')
if (token) {
request.headers.set('X-CSRF-TOKEN', token)
}
next()
})
So we get a file (an image file) in the front-end like so:
//html
<input type="file" ng-change="onFileChange">
//javascript
$scope.onFileChange = function (e) {
e.preventDefault();
let file = e.target.files[0];
// I presume this is just a binary file
// I want to HTTP Post this file to a server
// without using form-data
};
What I want to know is - is there a way to POST this file to a server, without including the file as form-data? The problem is that the server I am send a HTTP POST request to, doesn't really know how to store form-data when it receives a request.
I believe this is the right way to do it, but I am not sure.
fetch('www.example.net', { // Your POST endpoint
method: 'POST',
headers: {
"Content-Type": "image/jpeg"
},
body: e.target.files[0] // the file
})
.then(
response => response.json() // if the response is a JSON object
)
You can directly attach the file to the request body. Artifactory doesn't support form uploads (and it doesn't look like they plan to)
You'll still need to proxy the request somehow to avoid CORS issues, and if you're using user credentials, you should be cautious in how you treat them. Also, you could use a library like http-proxy-middleware to avoid having to write/test/maintain the proxy logic.
<input id="file-upload" type="file" />
<script>
function upload(data) {
var file = document.getElementById('file-upload').files[0];
var xhr = new XMLHttpRequest();
xhr.open('PUT', 'https://example.com/artifactory-proxy-avoiding-cors');
xhr.send(file);
}
</script>
Our front-end could not HTTP POST directly to the JFrog/Artifactory server. So we ended up using a Node.js server as a proxy, which is not very ideal.
Front-end:
// in an AngularJS controller:
$scope.onAcqImageFileChange = function (e) {
e.preventDefault();
let file = e.target.files[0];
$scope.acqImageFile = file;
};
// in an AngularJS service
createNewAcqImage: function(options) {
let file = options.file;
return $http({
method: 'POST',
url: '/proxy/image',
data: file,
headers: {
'Content-Type': 'image/jpeg'
}
})
},
Back-end:
const express = require('express');
const router = express.Router();
router.post('/image', function (req, res, next) {
const filename = uuid.v4();
const proxy = http.request({
method: 'PUT',
hostname: 'engci-maven.nabisco.com',
path: `/artifactory/cdt-repo/folder/${filename}`,
headers: {
'Authorization': 'Basic ' + Buffer.from('cdt-deployer:foobar').toString('base64'),
}
}, function(resp){
resp.pipe(res).once('error', next);
});
req.pipe(proxy).once('error', next);
});
module.exports = router;
not that we had to use a PUT request to send an image to Artifactory, not POST, something to do with Artifactory (the engci-maven.nabisco.com server is an Artifactory server). As I recall, I got CORS issues when trying to post directly from our front-end to the other server, so we had to use our server as a proxy, which is something I'd rather avoid, but oh well for now.
I'm using CodeIgniter with csrf protection enabled and Bootstrap 3 and twitter typeahead 0.9.3
I need to post my query with csrf key. I lost a day searching this. Tried beforeSend option but it doesn't work here is my code:
$('input[name="search"]').typeahead({
name:"companies",
remote:{
url:"{/literal}{site_url('tender/search_suppliers')}/{literal}",
beforeSend:function(jqXhr,settings){
settings.type = 'POST';
settings.data = { csrf_test_name: $.cookie('csrf_cookie_name')}
settings.hasData=true;
settings.hasContent=true;
return true;
}
}
});
This code is not posting and did not change type from GET to POST
SORRY for my english
I've run into the same problem RE: CSRF Protection in codeigniter and running any kind of ajax based function.
I added this function to my main site.js file that is loaded on all of my pages, and therefore gets included in all of my ajax calls:
$.ajaxSetup( data: { csrf_test_name: $.cookie('csrf_cookie_name') } );
I have a backbone app where any $.ajax() call I make to the PHP API works great and returns successful on a GET or POST request. However, when I try a model.fetch() or model.save() call (using the same endpoint), I am returned with:
XMLHttpRequest cannot load http://xyz.com.
Origin http://localhost is not allowed by Access-Control-Allow-Origin.
I know that's not much to go off of, but would there be a reason that backbone's ajax calls would be returning with errors, but when converted to just plain ajax calls, they are successful?
The headers in my PHP-based API on the server are:
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Headers: origin, content-type, accept');
header('Access-Control-Allow-Methods: OPTIONS, POST, GET, DELETE, PUT');
header('Access-Control-Max-Age: 86400');
Backbone is using Backbone.sync method to do ajax. It is doing same jquery.ajax with some default settings. This is the source code for Backbone.sync. You can match backbone's ajax setting with your ajax.
I am not sure about your approach. I did using fetch in the below manner. it worked fine for me. This might help you.
When you call .fetch, the model will trigger a request event, and when you receive it, parse it and set it to the model, the model will trigger a sync event.
var UserModel = Backbone.Model.extend({
url:'http://api.geonames.org/astergdemJSON?formatted=true&lat=50.01&lng=10.2&username=demo&style=full'
});
var MyView = Backbone.View.extend({
initialize: function() {
this.model = new UserModel();
this.listenTo(this.model,'sync', this.render);
this.model.fetch({success:this.success,error:this.error});
},
render: function() {
console.log('do awesome stuff here'+this.model.toJSON());
},
success:function(data){
console.log(data.attributes.status);
},
error:function(data){
console.log('error'+data.attributes.status)
}
});
var view = new MyView();
I am trying to implement CSRF protection in an app built using node.js using the express.js framework. The app makes abundant use of Ajax post calls to the server. I understand that the connect framework provides CSRF middleware, but I am not sure how to implement it in the scope of client-side Ajax post requests.
There are bits and pieces about this in other Questions posted here in stackoverflow, but I have yet to find a reasonably complete example of how to implement it from both the client and server sides.
Does anyone have a working example they care to share on how to implement this? Most of the examples I have seen, assume you are rendering the form on the server-side and then sending it (along with the embedded csrf_token form field) to the client-side. In my app, all content is rendered on the client-side (including templates) via Backbone.js. All the server does is provide values in JSON format, which are utilized by various Models in Backbone.js on the client-side. By my understanding I would need to retrieve the csrf_token via ajax first before it can be used. However, I am concerned this may be problematic from a security standpoint. Is this a valid concern?
It can be done by adding meta tag for CSRF token and then pass CSRF token with every Ajax request
Server
Add CSRF middleware
app.use(express.csrf());
app.use(function (req, res, next) {
res.locals.token = req.session._csrf;
next();
});
You can pass a CSRF token to the client side via, say, a meta tag. For ex, in Jade
meta(name="csrf-token", content="#{token}")
Client
jQuery has a feature called ajaxPrefilter, which lets you provide a callback to be invoked every Ajax request. Then set a header using ajaxPrefilter.
var CSRF_HEADER = 'X-CSRF-Token';
var setCSRFToken = function (securityToken) {
jQuery.ajaxPrefilter(function (options, _, xhr) {
if (!xhr.crossDomain) {
xhr.setRequestHeader(CSRF_HEADER, securityToken);
}
});
};
setCSRFToken($('meta[name="csrf-token"]').attr('content'));
server.js
...
// All Cookies/Sessions/BodyParser go first
app.use(express.csrf());
...
// Get the request
app.post('/ajax', function(req, res){
res.render('somelayout', {csrf_token: req.session._csrf});
});
In somelayout.jade
input(type='hidden', name='_csrf', value=csrf_token)
The CSRF middleware only generates the csrf token once per session, so it will probably not change for the duration of a user's visit.
Also, it doesn't check for the token on GET and HEAD requests. As long as the token is in the request (header, body, or query), you're good. That's pretty much all there is to it.
Since you are using Backbone.js for your application, I am assuming that it is a SPA and you initially load an index.html file, then make any other requests are made via ajax calls. If so, you can add a small snippet of JS code to your index.html file to hold the crsf token for any future ajax calls.
For example:
index.html (using Handlebars for templating...)
<!DOCTYPE html>
<html>
<head>
...
<script type="text/javascript">
$( function() {
window.Backbone.csrf = "{{csrfToken}}";
});
</script>
</head>
<body>
...
</body>
</html>
When you render the index.html file, give it the csrf token that the express framework generated here: req.session._csrf
When you use Backbone.js, it sets a global variable called Backbone. All that the previous function is doing is seting a property called csrf to the global Backbone object. And when you make an ajax call to POST data, simply add the Backbone.csrf variable to the data as _csrf that is being sent via the ajax call.
In Server:
app.use(function (req, res) {
res.locals._csrf = req.csrfToken();
res.locals.csrf_form_html = '<input type="hidden" name="_csrf" value="' + req.csrfToken() + '" >';
req.next();
});
In Client: (swig template)
var csrf = {{ _csrf|json|safe }};
$.ajaxSetup({
headers: {
'X-CSRF-Token': csrf
}
});
$.post("/create", data, function(result) {
console.log(result);
}).fail(function(){
console.log(arguments);
});
1. Add csrf protection middleware:
app.use(csrf({cookie: true}));
// csrf middleware
app.use(function (req, res, next) {
res.cookie('X-CSRF-Token', req.csrfToken());
// this line below is for using csrfToken value in normal forms (as a hidden input)
res.locals.csrfToken = req.csrfToken();
next();
});
// routing setup goes here
2. Add a beforeSend callback using $.ajaxSetup: (add this somewhere before all your ajax calls)
$.ajaxSetup({
beforeSend: function (xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRF-Token", getCookie('X-CSRF-Token'));
}
}
});
3. That's it! now you can send ajax requests and you don't need to add anything in headers or as a request parameter to pass through csrf.