Continue writing report

This commit is contained in:
Marko Korhonen 2020-05-03 17:20:09 +03:00
parent f36c9fef60
commit 834ed4b3e8
No known key found for this signature in database
GPG key ID: 911B85FBC6003FE5
11 changed files with 128 additions and 23 deletions

View file

@ -7,6 +7,8 @@ Palvelinpuolen kehykseksi valikoitui Actix web. Se on käytännössä vastine Ja
Actix web on puolestaan rakennettu hyödyntämällä Actix -sovelluskehystä, mikä on rakennettu löyhästi actor-mallin pohjalta. Actor-malli\cite{wiki:actor} on Carl Hewittin vuonna 1973 luoma matemaattinen ja tietotekninen malli rinnakkaisajosta. Tämän ansiosta Actix web on hyvin suorituskykyinen ja helposti skaalautuva ratkaisu rajapintoja rakennettaessa.
\clearpage
Actix web on myös hyvin integroitu Rustin vahvaan tyypitykseen. Erityisen vaikuttavaa oli se, että esimerkiksi tietyn rajapinnan päätepisteen POST-pyyntöön pystyy määrittämään parametriksi tietyn rakenteen (eng. structure).
\begin{code}
@ -23,7 +25,7 @@ Tällöin varmistutaan automaattisesti siitä, että kun asiakkaan POST-pyyntö
\label{code:json:registeruser}
\end{code}
Kun koodiesimerkin 7 funktioon ''register'' saapuu koodiesimerkin 8 mukainen JSON objekti, Actix huomaa väärän tyypin ja vastaa statuskoodilla ''400 Bad Request'', koska objektin parametri \mintinline{JSON}{"admin"} ei ole tyyppiä \mintinline{Rust}{bool}.
Kun koodiesimerkin \ref{code:rust:registeruser} funktioon ''register'' saapuu koodiesimerkin \ref{code:json:registeruser} mukainen JSON objekti, Actix huomaa väärän tyypin ja vastaa statuskoodilla ''400 Bad Request'', koska objektin parametri \mintinline{JSON}{"admin"} ei ole tyyppiä \mintinline{Rust}{bool}.
\subsection{Todentaminen}
@ -37,9 +39,9 @@ Todentamiseen päätin käyttää JSON Web Tokeneita. JSON Web Tokenit ovat stan
\label{code:json:jwt}
\end{code}
Tämä tokenin sisältö on kaikkien sen hallussapitäjien nähtävissä. 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.
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.
Eli esimerkiksi jos joku tämän sovelluksen käyttäjä, joka ei ole ylläpitäjä, koittaa tehdä itsestään ylläpitäjän muuttamalla tokenista parametrin \mintinline{JSON}{"admin"}: \mintinline{JSON}{false} arvoksi \mintinline{JSON}{true}, palvelimella suoritettava JWT validointifunktio, joka tietää oikean salasanan, näkee että tämä tunniste ei ole validi.
Eli esimerkiksi jos joku tämän sovelluksen käyttäjä, joka ei ole ylläpitäjä, koittaa tehdä itsestään ylläpitäjän muuttamalla tokenista parametrin \mintinline{JSON}{"admin": false} arvoksi \mintinline{JSON}{true}, palvelimella suoritettava JWT validointifunktio, joka tietää oikean salasanan, näkee että tämä tunniste ei ole enää validi.
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ää 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.
@ -75,11 +77,22 @@ Olen JavaScript-maailmassa tottunut siihen, että käyttöliittymäkehyksiin lö
\label{fig:login}
\end{figure}
\subsection{Reititys}
Reititykseen käytin Yew:n liitännäistä, yew\char`_routeria. Reititys asiakaspuolen ohjelmassa tarkoittaa sitä, että selaimen osoitepalkissa olevan polun mukaan käyttäjä reititetään oikeaan ohjelman osaan. Tämä liittyy käsitykseen yhden sivun ohjelmista (eng. single page application), joissa selain suorittaa yhden ohjelman, jonka jälkeen perinteisiä sivujen latauksia ei enää tapahtu. Ohjelma muokkaa osoitepalkissa näkyvää osoitetta, jonka pohjalta sitten reititys oikeaan komponenttiin tapahtuu.
Asiakaspuolen reititys vaatii myös palvelinpuolelta sen, että kaikki mahdolliset asiakaspuolen reitit palauttavat ohjelman. Toinen edellytys on se, että palvelin ei palauta uudelleenohjausta (HTTP 302), koska silloin myös osoitepalkissa oleva osoite muuttuu eikä sitä voida välittää asiakaspuolen ohjelmalle.
Yritin pitkään toteuttaa tällaista logiikkaa palvelinpuolelle siinä onnistumatta, mutta onnekseni yew\char`_routerin esimerkeistä löytyi esimerkkikoodia tämän saavuttamiseksi käyttämäni palvelinkehyksen kanssa. Päädyin laittamaan kaikki palvelimen omat reitit polun \mintinline{shell}{/api/} alle, ja asiakaspuolen ohjelman juureen (\mintinline{shell}{/}). Sitten määritin ns. ''catch-all'' reitin, joka palauttaa asiakaspuolen ohjelman ilman uudelleenohjausta. Tämä on Actixissa nimeltään \mintinline{shell}{default_service}.
\clearpage
Myös yew\char`_routerin kanssa oli omat haasteensa. Alkuun en saanut sitä toimimaan ollenkaan, vaan kaikki kutsut ohjattiin ensimmäisenä määritettyyn reittiin, mikä oli tässä tapauksessa ''/''. Ongelman syyksi paljastui yew\char`_routerin Switch-komponentin kokoava ''to'' makro. Ratkaisuna oli reitin ''/'' makron \mintinline{Rust}{#[to = "/"]} siirtäminen viimeiseksi listassa. Tarkempaa tietoa tästä ongelmasta voi lukea Yew:n dokumentaatiosta \cite{yew:router-problem}.
\section{Ongelmat}
Projektin loppuvaiheilla ilmeni muutamia ongelmia, mitä en ehtinyt enää ajan puutteen takia korjaamaan.
Palvelinpuolella keksin kokoava kirjasto, Actixin liitännäinen ''actix-identity'', kirjoittaa oletuksena keksiin parametrin \mintinline{JSON}{"HttpOnly": true}, mikä tarkoittaa sitä, että selain ei anna sen sisällä suoritettaville ohjelmille pääsyä tähän keksiin. Tämä on todella hyvä turvallisuusominaisuus, mikä estää haitallisia ohjelmia varastamaan käyttäjän kirjautumistietoja.
Palvelinpuolella keksin kokoava kirjasto, Actixin liitännäinen actix\char`_identity, kirjoittaa oletuksena keksiin parametrin \mintinline{JSON}{"HttpOnly": true}, mikä tarkoittaa sitä, että selain ei anna sen sisällä suoritettaville ohjelmille pääsyä tähän keksiin. Tämä on todella hyvä turvallisuusominaisuus, mikä estää haitallisia ohjelmia varastamasta käyttäjän kirjautumistietoja.
Suunnittelmana oli käyttää keksin tietoja asiakaspuolella reititykseen. Esimerkiksi jos keksiä ei ole olemassa, käyttäjä tulee reitittää sisäänkirjautumiskomponenttiin, missä keksi voidaan noutaa palvelimelta. Koska keksissä on tämä HttpOnly-parametri, tähän ei ole mahdollisuutta. Tämän parametrin voisi tietysti laittaa pois päältä, mutta ''actix-identity'' ei tarjoa tähän mitään mahdollisuutta.
Suunnittelmana oli käyttää keksin tietoja asiakaspuolella reititykseen. Esimerkiksi jos keksiä ei ole olemassa, käyttäjä tulee reitittää sisäänkirjautumiskomponenttiin, missä keksi voidaan noutaa palvelimelta. Koska keksissä on tämä HttpOnly-parametri, tähän ei ole mahdollisuutta. Tämän parametrin voisi tietysti laittaa pois päältä, mutta actix\char`_identity ei tarjoa tähän mitään mahdollisuutta.
Yhtenä ratkaisuna tähän ongelmaan olisi käyttää JSON Web Tokenin tallettamiseen keksien sijasta selaimen LocalStoragea. Tämä vaatisi lisää työtä sekä asiakaspuolella että palvelinpuolella ja valitettavasti tähän ei jäänyt enää aikaa.