Well I have a non-jQuery ajax function:
function callAjax(){ //will be sent to node server
var xmlhttp;
// compatible with IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
canAjax = true;
//do something
}
}
xmlhttp.open("GET", "string", true);
xmlhttp.send();
}
and a function that calls it:
function a(){
if(mouseIdle && canAjax){
callAjax()
}
}
This is kind of an api I give to my clients with a following:
<script src = "mysrc">
the problem is, anyone can easily delete these if's if they wanted(including their clients), and I can't figure out a way to make it uneditable, or at least preventable. I just want my javascript code to be untouchable from the inside, how can it be done?
Like Quentin said, you can't control JavaScript on the client side, that's just how the web works.
You could implement a simple auth system using tokens.
Your token should be something hard to guess to discourage brute force attacks, like the SHA256 hash of the current time. The empty hash for sha256 is below:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Then you could save this token key in your database (MongoDB, MySQL or other) and you need to obligate your client to send their token in each request they make.
After this you just need to validate the usage quota to that key and decide if you should serve or not.
It can't.
Anything you send to the client can be edited by the end user or duplicated, edited and placed on another website.
If you want to limit accesses to your Ajax endpoint, then you'll need to put the protection in on the server. For example, with IP address linked rate limiting.
Related
I'm working on an Electron app and trying to integrate the Easy Digital Downloads Software Licensing WordPress plugin. I haven't done much with HTTP communication in Electron/Javascript so this may be a naive question.
The problem: I am able to get a license activation response from my EDD server and while there is no specific error, for some reason a license is not activated. The odd thing is that if I use a URL and query string in a browser with the same data, the plugin responds as expected: I can activate, deactivate and check the status of a license.
So EDD seems to be working and there are no errors with Electron. But something is missing. Initially I was using the net Electron module but after this issue came up, I switched to using the example script from EDD (below) which uses XMLHttpRequest. With that I get the following response back:
{"success":true,"license":"valid","item_id":539,"item_name":"My
Awesome App","license_limit":1,"site_count":0,"expires":"2020-12-19
23:59:59","activations_left":1,"checksum":"f2d66c6844b37d1fa931b813c408",
"payment_id":248,"customer_name":"Marvin
Gardens","customer_email":"marvin#home.com","price_id":false}
Which is fine except that "activations_left":1 never changes and it should given "license_limit":1. So something is wrong.
On the other hand, if I use a URL with a query string in a browser, the "activations_left" is decremented and license activation only works once (as it should). For example, this works:
http://YOURSITE.com/?edd_action=activate_license&item_id=8&license=cc22c1ec86304b36883440e2e84cddff&url=http://licensedsite.com
My Question: is there some fundamental difference between these two methods? Is there something I need to add to my XMLHttpRequest? I have a support ticket open with EDD but I need to keep moving with this. And sorry to be so long-winded!
UPDATE:
#aw04 suggested I try using GET – just tried that and I "get" the same response as before: no error but also no activation.
Could there be some property which should (or shouldn't) be in the Electron request which is (or isn't) in a browser request by default?
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
console.log('xhttp.responseText', xhttp.responseText);
}
}
var url = "http://YOURSITE.com/?edd_action=activate_license&item_id=8&license=cc22c1ec86304b36883440e2e84cddff"
xhttp.open("GET", url);
xhttp.send();
var xhttp = new XMLHttpRequest();
var postUrl = 'http://<domain.com>/edd-sl/';
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
console.log(xhttp.responseText);
}
}
var data = {
edd_action: 'check_license',
license: '<license key>',
item_name: encodeURIComponent('<item name>'),
};
xhttp.open("POST", postUrl, true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.setRequestHeader("Access-Control-Allow-Origin", "http://local.dev");
var values = '';
for (var key in data){
values += key + '=' + data[ key ] + '&';
}
values = values.substring(0, values.length - 1);
xhttp.send(values);
Based on some help from Easy Digital Downloads support folks, this is resolved.
The issue had to do with a property in their Software Licensing plugin setup: "Do not check URL". I hadn't enabled that with the result that my API call from Electron failed and the one using a browser succeeded because the browser was adding headers that Electron was not.
After enabling "Do not check URL", calls from within Electron work. I guess there is also an option to pass in a URL, but since I am using EDD for licensing desktop software, that didn't seem like a needed option.
Anyway, hope this helps someone.
I have a little HTML5 game on my website that executes a Javascript function every time the game ends. The function is in an external script:
SubmitScore:(Gets called by game script)
function ONLINE_submitScore(strName,intMs) {
intMs = Math.round(intMs);
result = SQLCommand("online2.php?act=submit&name="+strName+"&score="+intMs);
return result;
}
SQLCommand: next to be called
function SQLCommand(url){
ajax=AjaxCaller();
if(ajax==false)
alert("AjaxCaller() failed!");
ajax.open("GET", url, true);
ajax.onreadystatechange=function(){
if(ajax.readyState==4){
if(ajax.status==200){
return ajax.responseText;
}
}
}
ajax.send(null);
}
AjaxCaller:
Final function called
function AjaxCaller(){
var xmlhttp=false;
try{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}catch(E){
xmlhttp = false;
}
}
if(!xmlhttp && typeof XMLHttpRequest!='undefined'){
xmlhttp = new XMLHttpRequest();
}
return xmlhttp;
}
The problem that I've encountered is that someone can easily use the developer console in Chrome or Firefox and execute the Javascript ONLINE_submitScore function to enter whatever score they please. What can I do to prevent this? Using a server-side password doesn't work because it's easy to see the POST request to read the password client-side.
If you don't have a login system that uses a one-way encrypted password, then there's no way to prevent anyone from putting in any score they want, as many times as they want to. At some point, of course, your high score board is just an open pipe to your database and anyone can spoof any value they want into it. Adding a login system and password you can limit the number of times a user tries to add a score - but you really have no way to check it. Yes, maybe you could write a crazy verification thing that happens within your game, and then gets replayed and checked on the backend (I don't know how your game works) but if someone wants to they can still probably fake a score.
[FWIW casinos work by running all results on the backend but casual/action mobile apps just don't work that way, the game takes place on the user's phone. Just obfuscate and make it harder for them to figure out how to spoof your system]
[Like, also a good starting point would be to not include a super-well-laid-out plan of a PHP file that I can hit from my browser to add a high score. Consider encoding that as part of a big gnarly random file you send up and then decoding it on the PHP side or something.]
Can you use CSRF in your form.
Here is an example http://www.wikihow.com/Prevent-Cross-Site-Request-Forgery-(CSRF)-Attacks-in-PHP
I have found a geocoder website that will give me some data that I need as a variable in my javascript code: http://geocoder.us/service/csv/geocode?zip=95472. the website returns only the content: 38.393314, -122.83666, Sebastopol, CA, 95472. I need pull this information from the website and put it into a string.
abc = "38.393314, -122.83666, Sebastopol, CA, 95472"
How can I accomplish this?
You can use AJAX:
var req = new XMLHttpRequest(); //Create an AJAX object
req.open('GET','http://geocoder.us/service/csv/geocode?zip=95472',true); //Location and method
req.send(); //Send
req.onreadystatechange = function() { //When it's ready
if (this.readyState === 4) { //... which is code 4
console.log(this.responseText); //Then you have the responseText
}
}
This only works when the request is from the same domain, tho (for security purposes). If you want it to work on any domain, you'll have to use a proxy.
You should use Javascript to make an ajax request to that URL and it will return the information you want in a format you specify, usually JSON. Depending on what Javascript libraries you are/aren't using, there's different ways you could do that -- probably the most common would be to use jQuery to make your request. Here's info on that API:
https://api.jquery.com/jQuery.get/
I'm debugging my php script and need to try to post data to by manually inputting it into the URL in my browser.
The javascript which sends the request is below. How do I enter the correct data into my browser so it's encoded in the same way as the javascript function? I tried encoding the string with http://meyerweb.com/eric/tools/dencoder/ and putting sendmail.php?q="the encoded string"... but that didn't work. Do I have to add more information?
function SendPHP(str, callback){
xmlhttp = new XMLHttpRequest();
str = "q=" + encodeURIComponent(str);
xmlhttp.open("POST","sendmail.php", true);
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState == 4){
inProgress=false;
if(xmlhttp.status == 200){
callback(xmlhttp.responseText);
}
}
};
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
if (inProgress==false){
inProgress=true;
xmlhttp.send(str);
}
else{
writeDisplayConsole("ERROR: xmlhttp fired twice!");
}
}
Use the Chrome Rest plugin extension https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo
You may want to look at Fiddler - the web debugging proxy. https://stackoverflow.com/questions/tagged/fiddler
One of Fiddler's features is Composer, which lets you edit a previously seen request, or create a new one from scratch. Check out e.g. this answer, it deals with a very similar issue: check POST request with Fiddler
I am trying to create a bookmarklet that, upon clicking, would request some information from the user (a url and a couple other fields in this case) and then send that data to a php page on my server and then display the result.
I would like to do an Ajax call for this so that I don't actually redirect to the new page, just get the data but I assume I would run into the "Same Origin Policy" limitation of Ajax.... is there any known way of basically doing the same thing?
Also, what would be the best way to pass the parameters? I already have a mechanism in place to recieve the parameters as a post message from a form...is there any way I could just reuse this?
You can set a bookmarklet by create a bookmark and add that piece of code below in location, but, according to same origin policy limitation, that will only work when the current tab is on the same location, here www.google.com.
If I've understand well your needs, that should be ok for your problem.
var request = new XMLHttpRequest();
request.open("GET", "http://www.google.com", true);
request.onreadystatechange = function() {
var done = 4, ok = 200;
if (request.readyState == done && request.status == ok) {
if (request.responseText) {
alert(request.responseText);
}
}
};
request.send(null);
I don't know if POST would work.
You won't be able to do a post, but a GET will work fine. If you're using something like jQuery, it will simply create a script tag with a src URL which would send the data you are looking to submit.
You will have to return JSON style data.
See: http://docs.jquery.com/Ajax/jQuery.getJSON
Alternatively, your bookmarklet could create an iframe on the page, and that could do you work of submitting the data (you could use post then) if you weren't looking to communicate between the iframe and the page itself, but instead just use user input to submit.