Kontinuasjonseksamen - Bidragsystem med CGI/XML
Type: Kodeanalyse av bidragsystem med CGI, JavaScript, XML og DTD
Fokus: Systemforståelse, filroller, kjørested-analyse, kodeforklaring linje-for-linje
Metode: Skriv egne svar først, sammenlign deretter med sensorveiledning
Gi et eksempel på hva du tenker systemet kan brukes til. Begrunn svaret.
Dette systemet kan brukes til mye forskjellig. Et hvilket som helst eksempel som er godt begrunnet får poeng her. Begrunnelse bør vektes minst 50%.
Viktig observasjon: Det er bare mulig å registrere ett bidrag pr. e-post siden tabellen har e-post som primærnøkkel.
Eksempler:
Dersom intet konkret eksempel er oppgitt, bør ingen poeng gis her.
Forklar hvilken rolle/hensikt hver av filene i systemet har. Begrunn hvordan du kommer frem til svarene.
Filer i systemet: compose.yaml, Dockerfile, index.html, bidrag.js, bidrag.cgi, bidrag.dtd
Begrunnelse må være med for å få full pott.
compose.yaml
Rolle: Gjør det enkelt å håndtere bygging, oppstart, nedstenging og omstart av systemet.
Begrunnelse: Filnavnet er standard-filnavnet for Docker-compose. Siden intet filnavn er oppgitt i build-kommandoen (kun `.`), leter Docker-compose etter en fil navngitt etter gjeldende standard.
Dockerfile
Rolle: Byggeoppskrift for container-bildet.
Begrunnelse: Standardfilnavn for container-bygging. Ligger i samme katalog som compose.yaml. Instruerer innhenting av html/js/dtd-filer, installerer database, legger til testdata og starter webtjener.
index.html
Rolle: Brukergrensesnitt for datainnsamling.
Begrunnelse: HTML-fil med input-felt (), knapper (
bidrag.js
Rolle: Inneholder funksjonen som sender data til serveren.
Begrunnelse: Importeres i index.html (linje 6). Funksjonen henter data fra tekstfelt, bygger XML-dokument og sender det til bidrag.cgi via fetch().
bidrag.cgi
Rolle: API som håndterer oppslag og endringer i databasen.
Begrunnelse: CGI-program (Common Gateway Interface). Kjøres av webserveren. Behandler GET/PUT/DELETE-requests, gjør SQL-queries og returnerer data. Gir ikke brukergrensesnitt.
bidrag.dtd
Rolle: Definerer gyldig format for XML-dokumenter.
Begrunnelse: Document Type Definition. Referert til i bidrag.js. Gjør det mulig å validere at data sendt fra klient er i riktig format.
Hvor kjøres (1) bidrag.js og (2) bidrag.cgi? Begrunn svaret ditt.
Begrunnelsen skal telle minst 50%.
bidrag.js kjøres i nettleseren
Begrunnelse:
document.querySelector() og fetch()) er klientside-funksjoner som kun finnes i nettlesere<script src=""> kjører alltid i nettleserenbidrag.cgi kjøres av webserveren i containeren
Begrunnelse:
Gi en detaljert beskrivelse av koden, linje for linje, i følgende filer:
Krav: Forklar hva hver linje gjør og hvordan den bidrar til systemets funksjonalitet.
1. FROM alpine - Starter med Alpine Linux (lettvekts distro) 2. RUN apk add busybox-extras libxml2-utils sqlite - Installerer pakker (httpd, xmllint, database) 3. COPY bidrag.cgi var/www/cgi-bin/bidrag.cgi - Kopierer CGI-script til riktig plassering 4. COPY index.html bidrag.js bidrag.dtd var/www/ - Kopierer frontend-filer til webroot 6-11. RUN echo "CREATE TABLE..." - Oppretter database med 5 kolonner (epost som PK) 13-16. RUN echo "INSERT INTO..." - Legger inn 3 testbrukere 18. RUN chmod a+w var/www/bidrag.db - Gir skriverettigheter til alle (nødvendig for CGI) 19. EXPOSE 80 - Deklarerer port 80 20. CMD httpd -p 80 -h /var/www -f -vv - Starter webserver
1. <!doctype html> - HTML5-deklarasjon
2-3. <html><head> - Start dokument og metadata
4. <meta charset="utf-8"> - UTF-8 tegnsett
5. <title> - Sidetittel
6. <script src="bidrag.js"> - Inkluderer JavaScript
7-8. </head><body> - Start body
10-14. <input...> - 5 tekstfelt for brukerinndata
16. <br/> - Linjeskift
18. <button onclick='bidrag("delete")'> - Slett-knapp
19. <button onclick='bidrag("put")'> - Endre-knapp
20. <a href='cgi-bin/bidrag.cgi'> - Liste-lenke (GET)
21-22. </body></html> - Avslutt dokument
1. function bidrag(funksjon) { - Funksjonsdeklarasjon
3-4. let h1/h2 - XML-deklarasjon og DOCTYPE
6-7. let u = new URL(...) - URL til CGI-script
9-13. let epost = document.querySelector(...)
- Henter verdier fra input-felt
15-21. let b = '<bidrag>...' - Bygger XML-string
23-29. fetch(u, {...}) - Sender HTTP-request
- method: funksjon (put/delete)
- body: h1+h2+b (komplett XML)
- headers: Content-Type application/xml
1. #!/bin/sh - Shebang (shell-script) 2. echo "Content-type:text/plain..." - HTTP-header 3. echo - Tom linje (markerer slutt på header) 5. if [ "$REQUEST_METHOD" = "GET" ] - Sjekk GET 6. echo "SELECT * FROM Bidrag" | sqlite3 -line - Hent alle bidrag fra database 7. exit - Avslutt hvis GET 9. else - Hvis ikke GET (PUT/DELETE) 10. KR=$(head -c "$HTTP_CONTENT_LENGTH") - Les request body 11-15. E=$(...) / P=$(...) osv. - Parser XML med xmllint og XPath - Henter epost, passord, kommentar, tittel, tekst 18-19. P2=$(echo "SELECT passord...") - Henter lagret passord for brukeren 21. if [ "$P" != "$P2" ]; then exit; fi - Validerer passord, avslutter hvis feil 25. if [ "$REQUEST_METHOD" = "DELETE" ] 26-28. echo "DELETE FROM Bidrag WHERE epost='$E'" - Sletter brukerens bidrag 30. elif [ "$REQUEST_METHOD" = "PUT" ] 31-32. echo "UPDATE Bidrag SET..." - Oppdaterer kommentar, tittel og tekst
Gi en vurdering av autentiseringsmekanismen som brukes i systemet.
Foreslå en forbedring. Begrunn svaret.
Autentiseringsmekanismen er ekstremt enkel og meget usikker:
Problemer:
Forbedringsforslag:
Viktigste forbedring: Passordhashing + HTTPS + sesjonshåndtering
Hvordan ville du endret systemet slik at det kun var mulig for autentiserte brukere å legge til nye bidrag/poster i databasen?
La svaret ditt være mest mulig konkret og detaljert.
Observasjon: Systemet implementerer sletting og endring for autentiserte brukere. Opprettelse av nye poster mangler.
Svaret må sørge for at skjemadata som kommer inn, blir oversatt til en SQL-setning med INSERT.
Viktig hensyn:
En bruker kan ikke ha flere bidrag siden e-postadressen er primærnøkkel. For å få full pott må dette addresseres ved å enten:
Løsning 1: Ny bruker-registrering
// I index.html:
<button onclick='nyBruker()'>Ny bruker</button>
function nyBruker() {
epost = document.querySelector('#epost').value;
passord = document.querySelector('#passord').value;
fetch(new URL('./cgi-bin/bidrag.cgi', base), {
method: 'post',
body: buildXML(epost, passord, '', '', ''),
headers: {'Content-Type': 'application/xml'}
});
}
// I bidrag.cgi:
elif [ "$REQUEST_METHOD" = "POST" ]; then
# Sjekk at e-post ikke finnes fra før
EXISTS=$(echo "SELECT COUNT(*) FROM Bidrag WHERE epost='$E'" | sqlite3 ../bidrag.db)
if [ "$EXISTS" -gt 0 ]; then
echo '{"error":"E-post finnes allerede"}'
exit
fi
# Opprett ny bruker
echo "INSERT INTO Bidrag (epost,passord,kommentar,tittel,tekst) VALUES ('$E','$P','$K','$T','$X')" | sqlite3 ../bidrag.db
fi
Løsning 2: Endre database-skjema
CREATE TABLE Bruker (
epost VARCHAR(200) PRIMARY KEY,
passord VARCHAR(200)
);
CREATE TABLE Bidrag (
id INTEGER PRIMARY KEY AUTOINCREMENT,
epost VARCHAR(200),
kommentar VARCHAR(1000),
tittel VARCHAR(100),
tekst VARCHAR(1000),
FOREIGN KEY(epost) REFERENCES Bruker(epost)
);
-- Nå kan én bruker ha flere bidrag
Velg en fil fra listen over for å vise koden...