Added some illustrations and improved JWT section

This commit is contained in:
Marko Korhonen 2020-05-09 17:29:49 +03:00
parent d12d412a84
commit 10fb260f6a
No known key found for this signature in database
GPG key ID: 911B85FBC6003FE5
7 changed files with 53 additions and 8 deletions

View file

@ -127,7 +127,7 @@
@misc{jwt:home, @misc{jwt:home,
title = {JSON Web Tokens}, title = {JSON Web Tokens},
url = "https://jwt.io", url = "https://jwt.io/introduction",
publisher = {}, publisher = {},
author = {Auth0}, author = {Auth0},
year = 2020, year = 2020,

View file

@ -2,7 +2,7 @@
Tein insinöörityön yhteydessä full-stack projektin, jossa sekä palvelin- että asiakaspuolen ohjelmointi tehtiin Rustilla. Tarkoituksena ei ollut saada aikaiseksi mitään todella monimutkaista ohjelmaa, vaan puhtaasti arvioida Rustin soveltuvuutta web-ohjelmointiin. Tein insinöörityön yhteydessä full-stack projektin, jossa sekä palvelin- että asiakaspuolen ohjelmointi tehtiin Rustilla. Tarkoituksena ei ollut saada aikaiseksi mitään todella monimutkaista ohjelmaa, vaan puhtaasti arvioida Rustin soveltuvuutta web-ohjelmointiin.
\section{Kehitysympäristön asennus} \section{Kehitysympäristön asennus}
Rust-projektin aloittamiseksi kehittäjä tarvitsee koneelleen Rustin paketinhallintatyökalun, Cargon (katso luku \ref{sect:paketinhallinta}). Olen itse Linux-käyttäjä, joten sain asennettua Cargon Linux-jakeluni ohjelmavarastosta. Windows-käyttäjille suosittelen käyttämään Rustup-asennusohjelmaa. Lisää tietoa Rustin asentamisesta saa Rustin kotisivuilta \cite{rust:install}. Rust-projektin aloittamiseksi kehittäjä tarvitsee koneelleen Rustin paketinhallintatyökalun, Cargon (katso luku \ref{sect:paketinhallinta}). Olen itse Linux-käyttäjä, joten sain asennettua Cargon Linux-jakeluni ohjelmavarastosta. Windows-käyttäjiä suosittelen käyttämään Rustup-asennusohjelmaa. Lisää tietoa Rustin asentamisesta saa Rustin kotisivuilta \cite{rust:install}.
Projektin saa initialisoitua komennolla \mintinline{shell}{cargo init projektinnimi}. Tämä komento luo hakemiston ''projektinnimi'', minkä sisällä on Cargon konfiguraatiotiedosto Cargo.toml, jossa voi määrittää projektin tiedot ja riippuvuudet. Projektin saa initialisoitua komennolla \mintinline{shell}{cargo init projektinnimi}. Tämä komento luo hakemiston ''projektinnimi'', minkä sisällä on Cargon konfiguraatiotiedosto Cargo.toml, jossa voi määrittää projektin tiedot ja riippuvuudet.
@ -44,23 +44,51 @@ Palvelinpuolen initialisointi ja käynnistäminen löytyvät liitteestä \ref{ap
Actix webin modulaarisuus mahdollisti myös helposti tarvittavien väliohjelmistojen sisällyttämisen ohjelman toimintaan. Actix identity -paketista löytyi tarvittavat palikat, joilla sain lisättyä itse kirjoittamani käyttäjän todentamistoiminnallisuuden suojaamaan haluttuja reittejä. Actix webin modulaarisuus mahdollisti myös helposti tarvittavien väliohjelmistojen sisällyttämisen ohjelman toimintaan. Actix identity -paketista löytyi tarvittavat palikat, joilla sain lisättyä itse kirjoittamani käyttäjän todentamistoiminnallisuuden suojaamaan haluttuja reittejä.
Todentamiseen päätin käyttää JSON Web Tokeneita. Ne ovat standardoitu (RFC 7519\cite{jwt:home}) tunnistautumistapa verkossa. Tokenit ovat merkkijonoja, jotka sisältävät JavaScript-objektin tekstimuodossa (JSON). Yhden tällaisen tokenin sisällön voi nähdä koodiesimerkissä \ref{code:json:jwt}. Todentamiseen päätin käyttää JSON Web Tokeneita. Ne ovat standardoitu (RFC 7519\cite{jwt:home}) tunnistautumistapa verkossa. Tokenit ovat merkkijonoja, jotka sisältävät JavaScript-objekteja tekstimuodossa (JSON). Token koostuu kolmesta osasta \cite{jwt:home}: ylätunnisteesta (eng. header), hyötykuormasta (eng. payload) ja allekirjoituksesta (eng. signature).
Ylätunniste koostuu JSON-objektista [koodiesimerkki \ref{code:json:jwt-header}], missä on määritelty tokenin tyyppi (tässä tapauksessa "JWT") ja allekirjoituksen algoritmi, mikä voi olla joko HS256 tai RSA.
\clearpage
\begin{code}
\inputminted{Rust}{code/jwt-header.json}
\captionof{listing}{JSON Web Tokenin ylätunniste}
\label{code:json:jwt-header}
\end{code}
\bigskip
Tokenin toisessa osassa, hyötykuormassa, on itse tokenin sisältö [koodiesimerkki \ref{code:json:jwt}]. Tokenin sisällön voi päättää kokonaan itse, vaikkakin joitakin standardeja kenttiä on määritetty. Esimerkiksi iss (issuer), sub (subject) ja exp (expiration time). Päätin sisällyttää myös tiedon siitä, että onko käyttäjä ylläpitäjä, koska tätä tietoa voi sitten käyttää asiakaspuolella esimerkiksi käyttöliittymän muokkaamiseen käyttäjän roolin perusteella. Usein myös käyttäjän nimi sisällytetään tokeniin. Tokenin sisältöä suunnitellessa kannattaa pitää mielessä, että sen sisältö on nähtävissä kaikille, joten se ei ole oikea paikka tallettaa salaista tietoa, kuten vaikka käyttäjän salasana.
\bigskip \bigskip
\begin{code} \begin{code}
\inputminted{Rust}{code/jwt.json} \inputminted{Rust}{code/jwt.json}
\captionof{listing}{Yhden JSON Web Tokenin sisältö tästä projektista} \captionof{listing}{Yhden JSON Web Tokenin hyötykuorma tästä projektista}
\label{code:json:jwt} \label{code:json:jwt}
\end{code} \end{code}
Tämä tokenin sisältö on kaikkien sen hallussapitäjien nähtävissä. Tokenin turvallisuus tulee siitä, että token on allekirjoitettu palvelinpuolella vain palvelimen tiedossa olevalla salasanalla niin, että jos tokenin sisältö muuttuu yhtään, palvelin näkee että se ei ole enää validi. \bigskip
Tokenin kolmesta osasta viimeinen on allekirjoitus. Se on koostettu ylätunnisteessa [koodiesimerkki \ref{code:json:jwt-header}] määritellyllä algoritmilla käyttämällä parametreina tokenin hyötykuormaa [koodiesimerkki \ref{code:json:jwt}] ja vain palvelimen tiedossa olevaa salasanaa. Koko tokenin turvallisuus perustuu juuri tähän allekirjoitukseen. Sen avulla palvelin voi varmistua siitä, että tokenia ei ole muokannut kukaan, kenellä ei ole tätä salasanaa.
Tokenia varmennettaessa hyötykuorma allekirjoitetaan uudelleen ja tätä uutta allekirjoitusta verrataan tokenin mukana tulleeseen allekirjoitukseen. Jos ne ovat samat, palvelin voi olla varma siitä että tokenin sisältöön voi luottaa. Tämän edellytyksenä tietysti on, että salasanaa on säilytetty turvallisella tavalla. JSON Web Tokenin kaikki osat on havainnollistettu kuvassa \ref{fig:jwt}.
\clearpage
\begin{figure}[h]
\centering
\includegraphics[width=\linewidth]{illustration/jwt.png}
\caption{Kaikki JWT:n osat havainnollistettuna käyttämällä jwt.io -sivustoa \cite{jwt:home}}
\label{fig:jwt}
\end{figure}
\bigskip
Otetaan esimerkkinä tämän sovelluksen käyttäjä Pasi. Pasi ei ole ylläpitäjä, mutta hän koittaa tehdä itsestään ylläpitäjän muuttamalla omasta tokenistaan parametrin \mintinline{JavaScript}{"admin": false} arvoksi \mintinline{JavaScript}{true}. Kun Pasi lähettää tämän muokatun tokenin palvelimelle, se viedään JWT-validointifunktioon. Palvelin huomaa, että token ei ole enää validi, koska sen sisältöä ei ole allekirjoitettu palvelimen salasanalla. Otetaan esimerkkinä tämän sovelluksen käyttäjä Pasi. Pasi ei ole ylläpitäjä, mutta hän koittaa tehdä itsestään ylläpitäjän muuttamalla omasta tokenistaan parametrin \mintinline{JavaScript}{"admin": false} arvoksi \mintinline{JavaScript}{true}. Kun Pasi lähettää tämän muokatun tokenin palvelimelle, se viedään JWT-validointifunktioon. Palvelin huomaa, että token ei ole enää validi, koska sen sisältöä ei ole allekirjoitettu palvelimen salasanalla.
Tokenin sisällön voi päättää kokonaan itse, vaikkakin joitakin standardeja kenttiä on määritetty. Esimerkiksi iss (issuer), sub (subject) ja exp (expiration time). Päätin sisällyttää myös tiedon siitä, että onko käyttäjä ylläpitäjä, koska tätä tietoa voi sitten käyttää asiakaspuolella esimerkiksi käyttöliittymän muokkaamiseen käyttäjän roolin perusteella. Usein myös käyttäjän nimi sisällytetään tokeniin. Tokenin sisältöä suunnitellessa kannattaa pitää mielessä, että sen sisältö on nähtävissä kaikille, joten se ei ole oikea paikka tallettaa salaista tietoa, kuten vaikka käyttäjän salasana. Päätin tallettaa edellä mainitun JSON Web Tokenin evästeeseen (eng. cookie), joka on standardi tapa tallettaa juuri tällaisia todentamiseen käytettäviä tietoja selaimissa. Evästeiden käyttämisen etu on se, että selain huolehtii sen tallettamisesta automaattisesti ilman lisätoimia kehittäjältä. Lisäksi selain sisällyttää sen seuraaviin kutsuihin automaattisesti.
Päätin tallettaa edellä mainitun JSON Web Tokenin evästeeseen (eng. cookie), joka on standardi tapa tallettaa juuri tällaisia todentamiseen käytettäviä tietoja selaimiin. Evästeiden käyttämisen etu on se, että selain huolehtii sen tallettamisesta automaattisesti ilman lisätoimia kehittäjältä. Lisäksi selain sisällyttää sen seuraaviin kutsuihin automaattisesti.
Projektin koko JWT-toteutus on liitteessä \ref{appx:jwt}. Projektin koko JWT-toteutus on liitteessä \ref{appx:jwt}.
@ -70,6 +98,17 @@ Lisäsin palvelimelle myös Cross-Origin Resource Sharing (CORS) \cite{wiki:cors
Lähes kaikki nykyiset web-ohjelmistot kuitenkin vaativat näiden ulkoisien resurssien käyttöä. CORS on tekniikka, jossa palvelin kertoo selaimelle sallitut osoitteet, mistä resursseja saa noutaa. CORS:n lisääminen tähän projektiin hoitui Actixin liitännäisellä actix\char`_cors. Lähes kaikki nykyiset web-ohjelmistot kuitenkin vaativat näiden ulkoisien resurssien käyttöä. CORS on tekniikka, jossa palvelin kertoo selaimelle sallitut osoitteet, mistä resursseja saa noutaa. CORS:n lisääminen tähän projektiin hoitui Actixin liitännäisellä actix\char`_cors.
\bigskip
\begin{figure}[h]
\centering
\includegraphics[width=\linewidth]{illustration/CORS.pdf}
\caption{Esimerkki Cross Origin Resource Sharing -tekniikasta}
\label{fig:cors}
\end{figure}
Kuvassa \ref{fig:cors} käyttäjä navigoi osoitteeseen "palvelin1.fi", josta selain lataa HTML-dokumentin. Tässä dokumentissa on kaksi kuvaa, "kuva1.jpg" ja "kuva2.png". Näistä kuva 1 tulee samalta palvelimelta kuin mistä dokumenttikin, se on sallitty Same-origin policy -käytännön takia. Kuva 2 tulee toiselta palvelimelta. Selain estää sen lataamisen, koska palvelin 1 ei ole kertonut asiakkaan selaimelle, että osoitteesta "palvelin2.fi" voi ladata resursseja. Jos kuvan 2 lataaminen haluttaisiin toimivaksi,
CORS:n asetusten määritys löytyy liitteestä \ref{appx:actix}. CORS:n asetusten määritys löytyy liitteestä \ref{appx:actix}.
\subsection{Tietokanta} \subsection{Tietokanta}

4
tex/code/jwt-header.json Normal file
View file

@ -0,0 +1,4 @@
{
"typ": "JWT",
"alg": "HS256"
}

View file

@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2020-05-09T14:09:21.468Z" agent="5.0 (X11)" etag="hRGFwXyjGoYKpa8Bt2xI" version="13.0.9" type="device"><diagram id="yY62ps6Dnq_cAM3BCDj3" name="Page-1">7Vldc5s4FP01fowHxIfh0XHd7sx2285k+/XUkUHGSjBihbChv74SSAYh7CStE894Ng8J90hI4p5zr66UibPYVu8ozDf/kBilE2DF1cR5MwEAhD7/LYBaAsBqgYTiuIXsDrjDP5EEVbcSx6jQOjJCUoZzHYxIlqGIaRiklOz1bmuS6rPmMEEGcBfB1ES/4phtWjTwrA7/C+Fko2a2LdmyhaqzBIoNjMm+BznLibOghLD2aVstUCp8p/zSvvf2SOthYRRl7CkvLH7Qz/X+w8/lDfvy4cv34mO9ZjeBXBur1QejmH+/NAllG5KQDKbLDr2lpMxiJEa1uNX1eU9IzkGbg/eIsVqSCUtGOLRh21S2ogqzb+L1aRgo+3tjW14o7TeVHL8x6p7xCVG8RQxRhWWM1t/6RjuW7bkK6AZrrLpvDYdrHSK8cNTPEipISSN0wrlKr5AmiJ3o5x3UwKMIEb4aWvP3KEohwzt9HVDqOTn0O7z6iWC+QmDJ0HOVRmXk2Y6lD9GuS77VCWdOKax73XLRoXj6PDLi5Wj8oR1QWb1P7KBGqs+QrXTGDqaldI+h406lQmL7DWboLocNX3ueqXRFyuEQZag6TbtJk3KD7oVAmvsuaRxy2qaXMMDMOk5sz4nP9xEY8ZGf8mlvV/whYc1nt8CaNIR23vP/K4lquCmaOJ7zDraXV12jGuXvycKZzN2asfbhvv2TiRG5hHF2mJcOJ+Yf1s5twL01DojlFDGdvYJR8oAWJCUiiDOSiSy1xmk6gGCKk4ybEadUxPutIBzzXD+XDVscx02KG5OLnvbOoJhwNvU0zbimZkLPlMwwjs+mGMdQzEO5g/b0Pk8MFh4JKFjk7W68xpXwmUbHBDixh4LYNbjjLQFYOb5/Hg/7gwxomQ4ORmIyeCkHu0dDMsY7JXjhczDNs6QXDb3mczOxDiIURWNMrAJP5PaXYAJ4F2bCe3wD4fVaLh6jOsU88Onju8iqzRDvVwcARg9Jkzc+loyPgs633XiW7tGZZzjUHttvjCrgbC71r82lHLm0T0PDha9RnquC+oYX5I6vV9WeDy5cVbvjJP5htQwGVSwIQrU7q0HalRn1slkQhz73W9j9+PrIYXPO6X4G0zy7LNcUdo7i2qyu3y3/bdhKd4jHHG9/K+K3mjaqudoCjR/zNeZGanrbHavpXyod2GMFxDBBZPFc3HsIN6awKHA0fvjWD97e6WP3kSO290gqOGPUy9r0d8/SPcq8EcYU9qdH7sEO4g4Pd09OIYNs5A4ldSRJnC0FmPVRmwKOHwiuNuptcPGwN0urQyqerrEIMVYWeFdeLykDToA1UpqBV+VkNpKKn3mb4o/dphiXNDrVYxckR+5SrlUL7jBAR+5NXjlAg9cWA/hfDONi4NX1pcUQntg75cXOtbJh5OnZy7HBze6fZ23h0/0H0ln+Ag==</diagram></mxfile>

BIN
tex/illustration/CORS.pdf Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2020-05-02T16:42:04.395Z" agent="5.0 (X11)" etag="fvheV9ftzY6ckkAXNWaH" version="13.0.5" type="device"><diagram id="nHt_eiJOzBJ3wmKHlSWK" name="Page-1">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</diagram></mxfile>

BIN
tex/illustration/jwt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB