Efficiënt scripten met jQuery 3.x
  • Over deze cursus
  • 1 Inleiding
  • 2 Inleiding tot JavaScript
    • Events en Actions
    • Syntax regels
    • JavaScript debugger
    • Variabelen
    • Operatoren
    • Voorwaardelijke instructies
    • Lussen
    • Functies
    • Functies in jQuery
    • Scope (zichtbaarheid) van variabelen
    • Objecten
    • Ingebouwde JavaScriptobjecten
  • 3 jQuery basis
  • 4 Elementen selecteren
    • Basis selectors
    • Hiërarchische selectors
    • Basisfilters
    • Inhoudsfilters
    • Attribuut selectors
    • Childfilters
    • Formulierfilters
    • Zichtbaarheidsfilters
    • Toepassing 1: gemeentelijst filteren (basisversie)
    • Toepassing 2: openingsuren markeren
  • 5 Selectie verfijnen (traversing)
    • Hiërarchische selectors
    • Filter methodes
    • Element looping: each()
    • Selecties in cascade: end()
    • Snelheidstest
    • Toepassing 1: gemeentelijst filteren (uitgebreide versie)
    • Toepassing 2: rating
  • 6 Events
    • Documentevents
    • Gebruikersevents
    • Event bubbling
    • Event methodes en properties
    • Hover-event: methode met een dubbele functie
    • De methode on()
    • Event handlers verwijderen
    • Toepassing 1: reactietest
  • 7 Animaties en effecten
    • Basiseffecten
    • Aangepaste animaties
    • Animatie pauzeren: delay()
    • Animatie beëindigen: finish()
    • Animatie afbreken: stop()
    • Versnellingsparameter
    • Toepassing 1: vloeiend scrollen
    • Toepassing 2: tabbladen
  • 8 DOM manipulatie
    • HTML-attributen
    • Object dimensies
    • Elementen toevoegen
    • Elementen verwijderen
    • Elementen vervangen
    • Elementen klonen
    • Toepassing 1: lightbox
  • 9 Inleiding tot AJAX
    • Historiek
    • Wat is XML?
    • Wat is JSON?
    • Requests filteren met GET en POST
    • Zes soorten AJAX requests
    • Same origin policy
    • Cross-site scripting
  • 10 AJAX zonder server-side scripting
    • Load()
    • $.getScript()
    • $.getJSON()
    • $.get() en $.post()
    • $.ajax()
    • Externe gegevens ophalen via JSONP
  • 11 AJAX met server-side scripting
    • Master/detailrelatie met load()
    • Master/detailrelatie met $.get()
    • Contactformulier verzenden met $.post()
    • Cross-site scripting (XSS)
Powered by GitBook
On this page
  • Het proxyscript
  • JSON: Google Geocoding
  • XML: iTunes feed
  1. 11 AJAX met server-side scripting

Cross-site scripting (XSS)

PreviousContactformulier verzenden met $.post()

Last updated 7 years ago

Met Cross-site scripting, afgekort als XSS, plaatsen we op onze webserver een proxyscript. Dit script haalt een extern bestand op en toont als resultaat een exacte kopie van de externe pagina. Door een AJAX call naar de proxypagina te maken, kunnen we op deze manier de same-origine policy beveiliging van de browser omzeilen.

Voor we de werking van het script bekijken gaan we nog even de PHP-configuratie controleren. De proxy maakt namelijk gebruik van de cURL-functie van PHP en deze is in de default configuratie van WAMPserver nog niet actief.

★ Open in een browser.

Het proxyscript

Het proxyscript is een universeel script waarmee u zowel HTML, JSON als XML kan ophalen. Geef de gewenste URL via de stringparameter url mee aan het script.

De URL bevat een &-teken en dit wordt door het proxyscript geïnterpreteerd als een eigen variabele, waardoor de pagina een foutief resultaat toont. Om dit te vermijden gaan we de URL via de JavaScriptmethode encodeURIComponent() coderen. De gecodeerde Google URL wordt dan: https%3A%2F%2Fwww.google.be%2Fsearch%3Fhl%3Dnl%26q%3Djquery

Als we deze string als URL aan het proxyscript geven, bekomen we wel het juiste resultaat.

Merk op dat bepaalde afbeeldingen op de pagina ontbreken. Alle afbeeldingen met relatieve paden worden niet getoond. Afbeeldingen met absolute paden zijn wel zichtbaar.

Werkt u op Windows hosting, gebruik dan het proxyscript proxy.asp. De werking is identiek aan proxy.php.

In dit hoofdstuk gaan we van elk datatype (HTML, JSON en XML) een voorbeeld uitwerken.

Net zoals in voorgaand hoofdstuk zijn we ook hier volledig afhankelijk van services van derden. Het is dus best mogelijk dat bij het uittesten van de voorbeelden in dit boek bepaalde oefeningen niet meer het gewenste resultaat opleveren.

JSON: Google Geocoding

★ Open de twee voorbeeldlinks (Vogelzang en mijr) bovenaan de pagina. ★ Bestudeer de JSON-structuur.

Indien de zoekopdracht geen resultaat oplevert, is results leeg en geeft status zero_results.

{
    "results" : [],
    "status" : "ZERO_RESULTS"
}

Bij een zoekopdracht met resultaat, staat status op OK. Results bevat nu deze structuur:

{
    "results" : [
        {
        "address_components" : [...],
        "formatted_address" : "Vogelzang, 9870 Zulte, België",
        "geometry" : {
            "bounds" : { ...},
            "southwest" : {...}, "location" : {
                "lat" : 50.93021560,
                "lng" : 3.46115240
            },
            "location_type" : "GEOMETRIC_CENTER", 
            "viewport" : {...}
        },
        "types" : [ "route" ]
        }, ...
        {...}
    ],
    "status" : "OK"
}

De waardes die ons interesseren zijn:

  • results.formatted_address

  • results.geometry.location.lat

  • results.geometry.location.lng

Net zoals in één van voorgaande toepassingen, kunnen we de coördinaten lat en lng opnieuw gebruiken om een statische map te genereren.

★ Open ajaxServer/XSS/googleGeo.html en bekijk de broncode.

$(function () {
    $('#mapsForm').submit(function (e) {
        e.preventDefault();
        $('.preloader-success').show();
        $('#aantal').text('');
        $('#map').empty().hide();
        var str = $(this).serialize();
        var url = 'http://maps.googleapis.com/maps/api/geocode/json?sensor=true&';
        var url = encodeURIComponent(url + str);
        $.getJSON('proxy.php?url=' + url, function (data) {
            if (data.status != 'OK') {
                $('#aantal').text('Geen locaties gevonden');
            } else {
                var aantal = data.results.length;
                $('#aantal').text(aantal + ' locaties gevonden');
                $.each(data.results, function (index, value) {
                    var adres = this.formatted_address;
                    var lat = this.geometry.location.lat;
                    var lng = this.geometry.location.lng;
                    var map = 'https://static-maps.yandex.ru/1.x/?lang=en-US&z=14&l=map&size=600,200&ll=' + lng + ',' + lat + '&pt=' + lng + ',' + lat + ',pm2rdl1';
                    $('#map').append('<p><b>' + adres + '</b><br>' + lat + ',' + lng + '</p>');
                    $('#map').append('<p><img src="' + map + '"></p>');
                });
                $('#map').show();
            }
        }).done(function () {
            $('.preloader-success').hide();
        }).fail(function (err) {
            console.log('error', err);
        });
    });
});

Telkens we nieuwe coördinaten opvragen, gaan we eerst de oude gegevens uit de section-tag #map wissen. Vervolgens wordt de URL van de op te vragen pagina samengesteld. Merk op dat de URL een &-teken bevat waardoor we de URL moeten coderen met encodeURIComponent().

Binnen de methode $.getJSON() wordt eerst de status gecontroleerd. Enkel indien de response resultaten bevat, gaan we de gewenste waardes binnen een each-lus uitlezen. De afbeelding wordt opgehaald en #map wordt opnieuw gevuld.

XML: iTunes feed

In het laatste voorbeeld gaan we een iTunes RSS-feed in onze pagina verwerken.

★ Open een willekeurig gegenereerde feed in Firefox of Internet Explorer ★ Bestudeer de XML-structuur.

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:im="http://itunes.apple.com/rss" ...>
    ...
    <title>iTunes Store: Top Albums</title>
    <entry>
        <im:image height="55">...</im:image>
        <im:image height="60">...</im:image>
        <im:image height="170">...</im:image>
        <content type="html">&lt;table ... /table&gt; </content>
    </entry>
    ...
</feed>

Het document is gestructureerd volgens een ATOM-feed. Apple heeft echter een eigen namespace aan de feed toegevoegd. Alle iTunes gerelateerde nodes beginnen met im:.

In onze toepassing gaan we drie nodes verwerken. De titel boven de thumbnails halen we uit de node titel. Het pad voor de thumbnails is de eerste im:img node. De volledige omschrijving staat in html binnen de node content.

Klik op een thumbnail om de omschrijving te tonen.

★ Open ajaxServer/XSS/itunes.html en bekijk de broncode.

$('#thumbs, #detail').hide();

$('#url').change(function (e) {
    $('.preloader-success').show();
    $('#thumbs, #detail').empty();
    var url = $(this).val();
    $.get('proxy.php?url=' + url, function (data) {
        $('#thumbs, #detail').show();
        $('h2').text($(data).find('title:first').text());
        var entry = $(data).find('entry');
        $.each(entry, function (index, value) {
            //Eerste selector (im\\:image:eq(1))  voor FF en IE, tweede (image:eq(1)) voor Chrome en Safari
            var img = $(this).find('im\\:image:eq(1), image:eq(1)').text();
            var title = $(this).find('title').text();
            var content = $(this).find('content').text();
            $('#thumbs').append('<img src="' + img + '" data-id="' + index + '">');
            $('#detail').append('<div id="entry' + index + '"><h3>' + title + '</h3>' + content + '</div>');
        });
        $('#detail div').not(':first').hide();
    }, 'xml').done(function () {
        $('.preloader-success').hide();
    }).fail(function (err) {
        console.error('error', err);
    });
}).change();

$('#thumbs').on('click', 'img', function () {
    var id = $(this).data('id');
    $('#detail div:visible').hide();
    $('#entry' + id).show();
});

Het uitlezen van de afbeelding im:image vraagt wat extra uitleg. Voor Chrome en Safari hoeft u geen rekening te houden met de prefix. Omdat de pagina drie dezelfde nodes bevat en we enkel de eerste node met de kleinste afbeelding gebruiken, wordt de selector image:eq(1). Voor Firefox en Internet Explorer is de prefix wel belangrijk. Een dubbelpunt moet u wel altijd laten voorafgaan door twee backslashes. De selector wordt dus im\\:image:eq(1). Door beide te combineren, werkt de selector find('im\\:image:eq(1), image:eq(1)') in alle browsers.

Binnen de each-lus worden alle afbeeldingen aan #thumbs toegevoegd. De index wordt via het attribuut data-id aan de afbeelding toegevoegd. Voor de eerste thumbnail wordt dit: <img src="https://...xxx.jpg" data-id="0" >. Dit nummer gebruiken we straks om de juiste details te tonen.

Alle content nodes komen in een div-tag binnen #detail te staan. Ook hier verwerken we de index in het id van de div-tag. Voor de eerste div-tag wordt dit: <div id="entry0">...</div>.

Op het einde van de each-lus worden alle div-tags, behalve de eerste, onzichtbaar gemaakt.

Telkens men op een thumbnail klikt, wordt de oude div-tag onzichtbaar en de geselecteerde div-tag wordt zichtbaar. Klik bijvoorbeeld op de tweede thumbnail. De variabele id is dan 1 en div-tag #entry1 wordt zichtbaar.

Indien de achtergrond groen kleurt, is de configuratie in orde en kan u verder met de oefeningen. Verschijnt de foutboodschap op een rode achtergrond, dan moet u de PHP-configuratie nog aanpassen!

★ Open volgende URL in een browser:

Stel dat de URL zelf ook nog stringparameters heeft, dan moeten we de string eerst coderen, anders loopt het grondig mis. Neem bijvoorbeeld:

Met de Google Geocoding API kan u de coördinaten van een straatnaam of van een volledig adres opvragen. Het resultaat wordt default in JSON-formaat aangeboden.

★ Open in een browser.

★ Open in een browser.

Via de link kan u desgewenst een eigen feed maken en deze aan de keuzelijst toevoegen.

http://jquery3.test/ajaxServer/XSS/curl.php
http://jquery3.test/ajaxServer/XSS/proxy.php?url=http://jquery.com
http://jquery3.test/...../proxy.php?url=https://www.google.be/search?hl=nl&q=jquery
https://developers.google.com/maps/documentation/geocoding/
http://jquery3.test/ajaxServer/XSS/googleGeo.html
http://jquery3.test//ajaxServer/XSS/iTunes.html
http://itunes.apple.com/rss
http://jquery3.test/ajaxServer/XSS/curl.php