Yksisivusovellusten, mobiilisovellusten ja RESTful API -palveluiden suosion kasvaessa web-kehittäjät kirjoita taustakoodi on muuttunut merkittävästi. AngularJS: n ja BackboneJS: n kaltaisilla tekniikoilla emme enää viettää paljon aikaa merkintöjen rakentamiseen, vaan rakennamme käyttöliittymiä, joita käyttöliittymämme kuluttavat. Taustamme on enemmän liiketoimintalogiikkaa ja dataa, kun taas esityslogiikka siirretään yksinomaan käyttöliittymään tai mobiilisovelluksiin. Nämä muutokset ovat johtaneet uusiin tapoihin todentamisen toteuttamiseksi nykyaikaisissa sovelluksissa.
Todennus on yksi kaikkien verkkosovellusten tärkeimmistä osista. Vuosikymmenien ajan evästeet ja palvelinpohjainen todennus olivat helpoin ratkaisu. Todennuksen käsitteleminen moderneissa mobiili- ja yksisivusovelluksissa voi kuitenkin olla hankalaa ja edellyttää parempaa lähestymistapaa. Tunnetuimmat ratkaisut sovellusliittymien todennusongelmiin ovat OAuth 2.0 ja JSON-verkkotunnus (JWT).
Mikä on JWT, ennen kuin pääsemme tähän JSON Web Token -oppaaseen?
JSON-verkkotunnusta käytetään tietojen lähettämiseen, jotka voidaan tarkistaa ja luottaa digitaalisen allekirjoituksen avulla. Se sisältää pienikokoisen ja URL-osoitteille turvallisen JSON-objektin, joka on allekirjoitettu salauksella sen aitouden varmistamiseksi ja joka voidaan myös salata, jos hyötykuorma sisältää arkaluontoisia tietoja.
Kompaktin rakenteensa vuoksi JWT: tä käytetään yleensä HTTP: ssä Authorization
otsikot tai URL-kyselyparametrit.
JWT on esitetty sekvenssinä base64url koodatut arvot, jotka on erotettu pisteillä.
Tässä on JWT-tunnusmerkki:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJpc3MiOiJ0b3B0YWwuY29tIiwiZXhwIjoxNDI2NDIwODAwLCJodHRwOi8vdG9wdGFsLmNvbS9qd3RfY2xhaW1zL2lzX2FkbWluIjp0cnVlLCJjb21wYW55IjoiVG9wdGFsIiwiYXdlc29tZSI6dHJ1ZX0. yRQYnWzskCZUxPwaQupWkiUzKELZ49eM7oWxAQK_ZXw
Otsikko sisältää tunnuksen metatiedot ja sisältää minimaalisesti allekirjoitustyypin ja salausalgoritmin. (Voit käyttää a JSON-muotoilija työkalu JSON-objektin tarkentamiseksi.)
Esimerkki otsikosta
{ 'alg': 'HS256', 'typ': 'JWT' }
Tämä JWT-esimerkkiotsikko ilmoittaa, että koodattu objekti on JSON-verkkotunnus ja että se on allekirjoitettu HMAC SHA-256 -algoritmilla.
Kun tämä on base64-koodattu, meillä on JWT: n ensimmäinen osa.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
JWT: n yhteydessä vaatimus voidaan määritellä lausekkeeksi oliosta (tyypillisesti käyttäjä) sekä lisämetadata itse tunnuksesta. Vaatimus sisältää tiedot, jotka haluamme lähettää, ja joita palvelin voi käyttää JSON Web Token -todennuksen asianmukaiseen käsittelyyn. Voimme esittää useita vaatimuksia; Näitä ovat rekisteröityjen vaatimusten nimet, julkisten vaatimusten nimet ja yksityisten vaatimusten nimet.
Rekisteröidyt JWT-vaateet
Nämä ovat väitteitä, jotka on rekisteröity EU: ssa IANA JSON Web Token -vaatimusrekisteri . Näiden JWT-vaatimusten ei ole tarkoitus olla pakollisia, vaan pikemminkin tarjota lähtökohta joukolle hyödyllisiä, yhteentoimivia väitteitä.
Nämä sisältävät:
Julkiset väitteet
Julkisilla vaatimuksilla on oltava törmäyksen kestävät nimet. Tekemällä nimi URI: ksi tai URN: ksi vältetään nimettyjä törmäyksiä JWT: lle, kun lähettäjä ja vastaanottaja eivät ole osa suljettua verkkoa.
Esimerkki julkisesta vaatimuksen nimestä voisi olla: https://www.toptal.com/jwt_claims/is_admin
, ja paras käytäntö on sijoittaa tuolle paikalle tiedosto, joka kuvaa vaatimusta, jotta siihen voidaan viitata dokumentoimiseksi.
Yksityiset vaatimukset
Yksityisiä vaatimusten nimiä voidaan käyttää paikoissa, joissa JWT: itä vaihdetaan vain suljetussa ympäristössä tunnettujen järjestelmien välillä, kuten yrityksen sisällä. Nämä ovat väitteitä, jotka voimme määritellä itse, kuten käyttäjätunnukset, käyttäjäroolit tai mikä tahansa muu tieto.
Käyttämällä väitteiden nimiä, joilla voi olla ristiriitaisia semanttisia merkityksiä suljetun tai yksityisen järjestelmän ulkopuolella, on törmäys, joten käytä niitä varoen.
On tärkeää huomata, että haluamme pitää verkkotunnuksen mahdollisimman pienenä, joten käytä vain tarvittavia tietoja julkisten ja yksityisten vaatimusten sisällä.
JWT-esimerkki hyötykuormasta
{ 'iss': 'toptal.com', 'exp': 1426420800, 'https://www.toptal.com/jwt_claims/is_admin': true, 'company': 'ApeeScape', 'awesome': true }
Tässä esimerkissä hyötykuormalla on kaksi rekisteröityä korvausvaatimusta, yksi julkinen vaatimus ja kaksi yksityistä saatavaa. Kun se on base64-koodattu, meillä on JWT: n toinen osa.
eyJpc3MiOiJ0b3B0YWwuY29tIiwiZXhwIjoxNDI2NDIwODAwLCJodHRwOi8vdG9wdGFsLmNvbS9qd3RfY2xhaW1zL2lzX2FkbWluIjp0cnVlLCJjb21wYW55IjoiVG9wdGFsIiwiYXdlc29tZSI6dHJ1ZX0
JWT-standardi noudattaa JSON Web Signature (JWS) -määrittelyä lopullisen allekirjoitetun tunnuksen luomiseksi. Se syntyy yhdistämällä koodattu JWT-otsikko ja koodattu JWT-hyötykuorma ja allekirjoittamalla se vahvalla salausalgoritmilla, kuten HMAC SHA-256. Palvelimen hallussa on allekirjoituksen salainen avain, joten se voi tarkistaa olemassa olevat tunnukset ja allekirjoittaa uudet.
$encodedContent = base64UrlEncode(header) + '.' + base64UrlEncode(payload); $signature = hashHmacSHA256($encodedContent);
Tämä antaa meille viimeisen osan JWT: stä.
yRQYnWzskCZUxPwaQupWkiUzKELZ49eM7oWxAQK_ZXw
On kriittistä käyttää TLS / SSL: ää yhdessä JWT: n kanssa man-in-the-middle-hyökkäysten estämiseksi. Useimmissa tapauksissa tämä riittää JWT-hyötykuorman salaamiseen, jos se sisältää arkaluontoisia tietoja. Jos kuitenkin haluamme lisätä ylimääräisen suojakerroksen, voimme salata itse JWT-hyötykuorman käyttämällä JSON-verkkosalaus (PLAY) -määritys.
Tietenkin, jos haluamme välttää JWE: n käytön aiheuttamat lisäkustannukset, toinen vaihtoehto on yksinkertaisesti pitää arkaluontoiset tiedot tietokannassamme ja käyttää tunnustamme ylimääräisiin API-kutsuihin palvelimelle aina, kun meidän on käytettävä arkaluonteisia tietoja.
Ennen kuin voimme nähdä kaikki JWT-todennuksen edut, meidän on tarkasteltava tapaa, jolla todennus on tehty aiemmin.
Koska HTTP-protokolla on tilaton, on oltava mekanismi käyttäjätietojen tallentamiseksi ja tapa todentaa käyttäjä jokaisessa myöhemmässä pyynnössä sisäänkirjautumisen jälkeen. Useimmat verkkosivustot käyttävät evästeitä käyttäjän istuntotunnuksen tallentamiseen.
Kuinka se toimii
Selain lähettää palvelimelle POST-pyynnön, joka sisältää käyttäjän tunnuksen ja salasanan. Palvelin vastaa evästeellä, joka on asetettu käyttäjän selaimeen, ja sisältää istunnon tunnuksen käyttäjän tunnistamiseksi.
Palvelimen on löydettävä jokainen myöhempi pyyntö istunto ja poistettava se käytöstä, koska käyttäjätiedot tallennetaan palvelimelle.
Vaikea skaalata : Palvelimen on luotava istunto käyttäjälle ja säilytettävä se jossain palvelimessa. Tämä voidaan tehdä muistissa tai tietokannassa. Jos meillä on hajautettu järjestelmä, meidän on varmistettava, että käytämme erillistä istuntotallennustilaa, jota ei ole yhdistetty sovelluspalvelimeen.
Alkuperäisten pyyntöjen jakaminen (CORS) : Kun haemme AJAX-kutsuja resurssin hakemiseksi toisesta verkkotunnuksesta ('cross-origin'), meillä voi olla ongelmia kiellettyjen pyyntöjen kanssa, koska oletusarvoisesti HTTP-pyynnöt eivät sisällä evästeitä ristiin alkuperää koskevissa pyynnöissä.
Yhdistäminen verkkokehykseen : Kun käytät palvelinpohjaista todennusta, olemme sidoksissa kehyksemme todennusjärjestelmään. On todella vaikeaa tai jopa mahdotonta jakaa istuntotietoja eri verkkokehysten välillä, jotka on kirjoitettu eri ohjelmointikielillä.
Tunnuspohjainen / JWT-todennus on valtioton, joten käyttäjätietoja ei tarvitse tallentaa istuntoon. Tämä antaa meille mahdollisuuden skaalata sovelluksemme huolimatta siitä, mihin käyttäjä on kirjautunut. Voimme helposti käyttää samaa tunnusta haettaessa suojattua resurssia muulta verkkotunnukselta kuin siihen, johon olemme kirjautuneet.
Kuinka JSON-verkkotunnukset toimivat
Selain tai mobiiliasiakas pyytää todentamispalvelimelta pyynnön, joka sisältää käyttäjän kirjautumistiedot. Todennuspalvelin luo uuden JWT-käyttöoikeustunnuksen ja palauttaa sen asiakkaalle. Jokaisessa pyynnössä rajoitetulle resurssille asiakas lähettää pääsykoodin kyselymerkkijonossa tai Authorization
otsikko. Palvelin vahvistaa sitten tunnuksen ja, jos se on kelvollinen, palauttaa suojatun resurssin asiakkaalle.
Todennuspalvelin voi allekirjoittaa tunnuksen millä tahansa suojatulla allekirjoitusmenetelmällä. Esimerkiksi symmetrisen avaimen algoritmia, kuten HMAC SHA-256, voidaan käyttää, jos on olemassa suojattu kanava salaisen avaimen jakamiseksi kaikkien osapuolten kesken. Vaihtoehtoisesti voidaan käyttää myös epäsymmetristä julkisen avaimen järjestelmää, kuten RSA, mikä eliminoi tarpeen avainten edelleen jakamiseksi.
Valtaton, helpompi skaalata : Tunnus sisältää kaikki tiedot käyttäjän tunnistamiseksi, jolloin istuntotilaa ei tarvita. Jos käytämme kuormituksen tasapainotinta, voimme siirtää käyttäjän mihin tahansa palvelimeen sen sijaan, että olisimme sidoksissa samaan palvelimeen, johon olemme kirjautuneet.
Uudelleenkäytettävyys : Meillä voi olla useita erillisiä palvelimia, jotka toimivat useilla alustoilla ja toimialueilla ja käyttävät samaa tunnusta uudelleen käyttäjän todentamiseen. On helppo rakentaa sovellus, joka jakaa käyttöoikeudet toisen sovelluksen kanssa.
JWT-turvallisuus : Koska emme käytä evästeitä, meidän ei tarvitse suojautua sivustojen välisten pyyntöjen väärentämisen (CSRF) hyökkäyksiltä. Meidän pitäisi silti salata tunnuksemme JWE: n avulla, jos joudumme sisällyttämään niihin arkaluontoisia tietoja, ja lähettämään tunnuksemme HTTPS: n kautta estämään keskellä olevat ihmiset-hyökkäykset.
Esitys : Ei ole palvelinpuolen hakua istunnon löytämiseksi ja deserialisoimiseksi jokaisesta pyynnöstä. Ainoa asia, joka meidän on tehtävä, on laskea HMAC SHA-256 tunnuksen vahvistamiseksi ja sen sisällön jäsentämiseksi.
Tässä JWT-opetusohjelmassa aion osoittaa, kuinka perustodennus voidaan toteuttaa JSON-verkkotunnisteilla kahdessa suositussa verkkotekniikassa: Laravel 5 backend-koodille ja AngularJS frontend Single Page -sovelluksen (SPA) esimerkille. (Löydät koko esittelyn tässä ja lähdekoodi tämä GitHub-arkisto jotta voit seurata opetusohjelmaa.)
Tässä JSON-verkkomerkkiesimerkissä ei käytetä minkäänlaista salausta vaatimuksissa lähetettyjen tietojen luottamuksellisuuden varmistamiseksi. Käytännössä tämä on usein okei, koska TLS / SSL salaa pyynnön. Jos tunnus kuitenkin sisältää arkaluontoisia tietoja, kuten käyttäjän sosiaaliturvatunnuksen, se tulisi myös salata JWE: llä.
Käytämme Laravelia käsittelemään käyttäjien rekisteröintiä, säilyttämään käyttäjätietoja tietokantaan ja toimittamaan joitain rajoitettuja tietoja, jotka tarvitsevat todennuksen Angular-sovelluksen kuluttamiseksi. Luomme esimerkin API-aliverkkotunnuksesta, joka simuloi myös alkuperän välistä resurssien jakamista (CORS).
Asennus ja projektin käynnistys
Laravelin käyttämiseksi meidän on asennettava Säveltäjä koneemme paketinhallinta. Laravelissa kehittäessäni suosittelen Lagravel Homesteadin valmiiksi pakattua Vagrantin ”laatikkoa”. Se tarjoaa meille täydellisen kehitysympäristön käyttöjärjestelmästämme riippumatta.
Helpoin tapa käynnistää JWT Laravel -sovelluksemme on käyttää Composer-pakettia Laravel Installer.
composer global require 'laravel/installer=~1.1'
Nyt olemme kaikki valmiita luomaan uuden Laravel-projektin suorittamalla laravel new jwt
Jos sinulla on kysyttävää tästä prosessista, ota yhteyttä virkamieheen Laravel-dokumentaatio .
Kun olemme luoneet Laravel 5 -perussovelluksen, meidän on määritettävä Homestead.yaml
, joka määrittää kansiokartoitukset ja toimialueiden kokoonpanot paikallista ympäristöämme varten.
Esimerkki Homestead.yaml
tiedosto:
--- ip: '192.168.10.10' memory: 2048 cpus: 1 authorize: /Users/ttkalec/.ssh/public.psk keys: - /Users/ttkalec/.ssh/private.ppk folders: - map: /coding/jwt to: /home/vagrant/coding/jwt sites: - map: jwt.dev to: /home/vagrant/coding/jwt/public - map: api.jwt.dev to: /home/vagrant/coding/jwt/public variables: - key: APP_ENV value: local
Kun olemme käynnistäneet Vagrant-laatikkomme vagrant up
-merkillä komento ja kirjaudu siihen vagrant ssh
: lla, siirrymme aiemmin määritettyyn projektihakemistoon. Yllä olevassa esimerkissä tämä olisi /home/vagrant/coding/jwt
. Voimme nyt suorittaa php artisan migrate
komennolla tarvittavien käyttäjätaulukoiden luomiseksi tietokantaan.
Säveltäjän riippuvuuksien asentaminen
Onneksi kehittäjien yhteisö työskentelee Laravelin parissa ja ylläpitää monia upeita paketteja, joita voimme käyttää uudelleen ja laajentaa sovellustamme. Tässä esimerkissä käytämme tymon/jwt-auth
, kirjoittanut Sean Tymon, merkkien käsittelystä palvelinpuolella, ja barryvdh/laravel-cors
, kirjoittanut Barry vd. Heuvel, CORS: n käsittelyyn.
jwt-auth
Vaadi tymon/jwt-auth
paketti composer.json
ja päivitä riippuvuutemme.
composer require tymon/jwt-auth 0.5.*
Lisää JWTAuthServiceProvider
meidän app/config/app.php
palveluntarjoajat.
'TymonJWTAuthProvidersJWTAuthServiceProvider'
Seuraavaksi app/config/app.php
tiedosto aliases
-kohdassa taulukko, lisätään JWTAuth
julkisivu.
'JWTAuth' => 'TymonJWTAuthFacadesJWTAuth'
Lopuksi haluamme julkaista paketin config seuraavalla komennolla: php artisan config: publish tymon / jwt-auth
JSON-verkkomerkit salataan salaisella avaimella. Voimme luoda kyseisen avaimen käyttämällä php artisan jwt:generate
komento. Se sijoitetaan config/jwt.php
-sivullemme tiedosto. Tuotantoympäristössä emme kuitenkaan koskaan halua, että salasanamme tai API-avaimemme ovat kokoonpanotiedostoissa. Sen sijaan meidän pitäisi sijoittaa ne palvelinympäristön muuttujien sisään ja viitata niihin määritystiedostoon env
toiminto. Esimerkiksi:
'secret' => env('JWT_SECRET')
Voimme saada lisätietoja tästä paketista ja kaikista sen kokoonpanoasetuksista Githubissa .
laravel-cors
Vaadi barryvdh/laravel-cors
paketti composer.json
ja päivitä riippuvuutemme.
composer require barryvdh/laravel-cors [email protected]
Lisää CorsServiceProvider
meidän app/config/app.php
palveluntarjoajat.
'BarryvdhCorsCorsServiceProvider'
Lisää sitten väliohjelmisto app/Http/Kernel.php
-palveluumme.
'BarryvdhCorsMiddlewareHandleCors'
Julkaise kokoonpano paikalliseen config/cors.php
tiedosto php artisan vendor:publish
komento.
Esimerkki cors.php
tiedoston kokoonpano:
return [ 'defaults' => [ 'supportsCredentials' => false, 'allowedOrigins' => [], 'allowedHeaders' => [], 'allowedMethods' => [], 'exposedHeaders' => [], 'maxAge' => 0, 'hosts' => [], ], 'paths' => [ 'v1/*' => [ 'allowedOrigins' => ['*'], 'allowedHeaders' => ['*'], 'allowedMethods' => ['*'], 'maxAge' => 3600, ], ], ];
HTTP-pyyntöjen reititys ja käsittely
Lyhyyyden vuoksi laitan kaikki koodini reitit.php-tiedostoon, joka on vastuussa Laravel-reitityksestä ja pyyntöjen siirtämisestä ohjaimille. Luomme yleensä erilliset ohjaimet kaikkien HTTP-pyyntöjemme käsittelemiseksi ja pidämme koodimme modulaarisena ja puhtaana.
Ladataan AngularJS SPA -näkymämme
Route::get('/', function () { return view('spa'); });
käyttäjän rekisteröinti
Kun teemme POST
pyyntö /signup
Käyttäjänimellä ja salasanalla yritämme luoda uuden käyttäjän ja tallentaa sen tietokantaan. Kun käyttäjä on luotu, JWT luodaan ja palautetaan JSON-vastauksen kautta.
Route::post('/signup', function () { $credentials = Input::only('email', 'password'); try { $user = User::create($credentials); } catch (Exception $e) { return Response::json(['error' => 'User already exists.'], HttpResponse::HTTP_CONFLICT); } $token = JWTAuth::fromUser($user); return Response::json(compact('token')); });
Käyttäjän kirjautuminen
Kun teemme POST
pyyntö /signin
käyttäjänimellä ja salasanalla varmistamme, että käyttäjä on olemassa ja palauttaa JWT: n JSON-vastauksen kautta.
Route::post('/signin', function () { $credentials = Input::only('email', 'password'); if ( ! $token = JWTAuth::attempt($credentials)) { return Response::json(false, HttpResponse::HTTP_UNAUTHORIZED); } return Response::json(compact('token')); });
Rajoitetun resurssin noutaminen samasta toimialueesta
Kun käyttäjä on kirjautunut sisään, voimme hakea rajoitetun resurssin. Olen luonut reitin /restricted
joka simuloi resurssia, joka tarvitsee todennetun käyttäjän. Tätä varten pyyntö Authorization
otsikon tai kyselymerkkijonon on annettava JWT, jotta backend voi tarkistaa.
Route::get('/restricted', [ 'before' => 'jwt-auth', function () { $token = JWTAuth::getToken(); $user = JWTAuth::toUser($token); return Response::json([ 'data' => [ 'email' => $user->email, 'registered_at' => $user->created_at->toDateTimeString() ] ]); } ]);
Tässä esimerkissä käytän jwt-auth
jwt-auth
-sovelluksessa oleva väliohjelmisto pakkaa käyttäen 'before' => 'jwt-auth'
. Tätä väliohjelmistoa käytetään pyynnön suodattamiseen ja JWT-tunnuksen vahvistamiseen. Jos tunnus on virheellinen, sitä ei ole tai se on vanhentunut, väliohjelmisto heittää poikkeuksen, jonka voimme saada kiinni.
Laravel 5: ssä voimme saada poikkeuksia käyttämällä app/Exceptions/Handler.php
tiedosto. render
toiminnolla voimme luoda HTTP-vastauksia heitetyn poikkeuksen perusteella.
public function render($request, Exception $e) { if ($e instanceof TymonJWTAuthExceptionsTokenInvalidException) { return response(['Token is invalid'], 401); } if ($e instanceof TymonJWTAuthExceptionsTokenExpiredException) { return response(['Token has expired'], 401); } return parent::render($request, $e); }
Jos käyttäjä on todennettu ja tunnus on voimassa, voimme palauttaa rajoitetut tiedot käyttöliittymään turvallisesti JSON: n kautta.
Rajoitettujen resurssien hakeminen API-aliverkkotunnuksesta
Seuraavassa JSON-verkkomerkkiesimerkissä otamme toisen lähestymistavan tunnuksen vahvistamiseen. Sen sijaan, että käyttäisit jwt-auth
väliohjelmisto, käsittelemme poikkeuksia manuaalisesti. Kun teemme POST
pyyntö API-palvelimelle api.jwt.dev/v1/restricted
, teemme ristilähtöpyynnön ja meidän on otettava CORS käyttöön taustalla. Onneksi olemme jo määrittäneet CORS: n config/cors.php
tiedosto.
Route::group(['domain' => 'api.jwt.dev', 'prefix' => 'v1'], function () { Route::get('/restricted', function () { try { JWTAuth::parseToken()->toUser(); } catch (Exception $e) { return Response::json(['error' => $e->getMessage()], HttpResponse::HTTP_UNAUTHORIZED); } return ['data' => 'This has come from a dedicated API subdomain with restricted access.']; }); });
Käytämme AngularJS: ää käyttöliittymänä. Luotamme API-kutsuihin Laravelin takaosan todennuspalvelimelle käyttäjän todennusta ja näytetietoja varten sekä API-palvelimelle ristiinlähtöisiä esimerkkitietoja varten. Kun menemme projektin kotisivulle, taustakuva palvelee resources/views/spa.blade.php
näkymä, joka käynnistää Angular-sovelluksen.
Tässä on Angular-sovelluksen kansiorakenne:
public/ |-- css/ `-- bootstrap.superhero.min.css |-- lib/ |-- loading-bar.css |-- loading-bar.js `-- ngStorage.js |-- partials/ |-- home.html |-- restricted.html |-- signin.html `-- signup.html `-- scripts/ |-- app.js |-- controllers.js `-- services.js
Kulmasovelluksen käynnistäminen
spa.blade.php
sisältää sovelluksen suorittamiseen tarvittavat paljaset. Käytämme muotoilussa Twitter Bootstrapia ja mukautetun teeman Saappaat . Jos haluat saada visuaalista palautetta AJAX-puhelua soitettaessa, käytämme kulmakuormitustanko komentosarja, joka sieppaa XHR-pyynnöt ja luo latauspalkin. Otsikko-osassa on seuraavat tyylitaulukot:
ngStorage
Merkinnän alatunniste sisältää viitteitä kirjastoihin sekä mukautettuja komentosarjoja kulmamoduuleille, ohjaimille ja palveluille.
Authorization
Käytämme token
kirjasto AngularJS: lle tallentamaan tunnuksia selaimen paikalliseen tallennustilaan, jotta voimme lähettää sen jokaisesta pyynnöstä Toggle navigation JWT Angular example
otsikko.
Tuotantoympäristössä tietysti minimoimme ja yhdistämme kaikki komentosarjatiedostot ja tyylitaulukot suorituskyvyn parantamiseksi.
Olen luonut Bootstrap-sovelluksella navigointipalkin, joka muuttaa sopivien linkkien näkyvyyttä käyttäjän kirjautumistilasta riippuen. Sisäänkirjautumistila määräytyy app.js
-luvun läsnäololla muuttuja ohjaimen piirissä.
angular.module('app', [ 'ngStorage', 'ngRoute', 'angular-loading-bar' ]) .constant('urls', { BASE: 'http://jwt.dev:8000', BASE_API: 'http://api.jwt.dev:8000/v1' }) .config(['$routeProvider', '$httpProvider', function ($routeProvider, $httpProvider) { $routeProvider. when('/', { templateUrl: 'partials/home.html', controller: 'HomeController' }). when('/signin', { templateUrl: 'partials/signin.html', controller: 'HomeController' }). when('/signup', { templateUrl: 'partials/signup.html', controller: 'HomeController' }). when('/restricted', { templateUrl: 'partials/restricted.html', controller: 'RestrictedController' }). otherwise({ redirectTo: '/' });
Reititys
Meillä on tiedosto nimeltä HomeController
joka on vastuussa kaikkien etupääreittiemme konfiguroinnista.
RestrictedController
Täällä voimme nähdä, että olemme määrittäneet neljä reittiä, joita joko Authorization
hoitaa tai $httpProvider.interceptors.push(['$q', '$location', '$localStorage', function ($q, $location, $localStorage) { return { 'request': function (config) { config.headers = config.headers || {}; if ($localStorage.token) { config.headers.Authorization = 'Bearer ' + $localStorage.token; } return config; }, 'responseError': function (response) { if (response.status === 401 || response.status === 403) { $location.path('/signin'); } return $q.reject(response); } }; }]);
. Jokainen reitti vastaa osittaista HTML-näkymää. Olemme myös määrittäneet kaksi vakiota, jotka sisältävät URL-osoitteet HTTP-pyynnöille backendille.
Pyydä sieppaajaa
AngularJS: n $ http -palvelu antaa meille mahdollisuuden kommunikoida taustajärjestelmän kanssa ja tehdä HTTP-pyyntöjä. Meidän tapauksessamme haluamme siepata kaikki HTTP-pyynnöt ja pistää niihin controllers.js
otsikko, joka sisältää JWT: n, jos käyttäjä on todennettu. Voimme myös käyttää keskeyttäjää luomaan globaalin HTTP-virhekäsittelijän. Tässä on esimerkki sieppaimestamme, joka syöttää tunnuksen, jos se on saatavana selaimen paikallisessa tallennustilassa.
HomeController
Ohjaimet
Kohdassa RestrictedController
tiedosto, olemme määrittäneet sovelluksellemme kaksi ohjainta: HomeController
ja Auth
. angular.module('app') .controller('HomeController', ['$rootScope', '$scope', '$location', '$localStorage', 'Auth', function ($rootScope, $scope, $location, $localStorage, Auth) { function successAuth(res) { $localStorage.token = res.token; window.location = '/'; } $scope.signin = function () { var formData = { email: $scope.email, password: $scope.password }; Auth.signin(formData, successAuth, function () { $rootScope.error = 'Invalid credentials.'; }) }; $scope.signup = function () { var formData = { email: $scope.email, password: $scope.password }; Auth.signup(formData, successAuth, function () { $rootScope.error = 'Failed to signup'; }) }; $scope.logout = function () { Auth.logout(function () { window.location = '/' }); }; $scope.token = $localStorage.token; $scope.tokenClaims = Auth.getTokenClaims(); }])
käsittelee sisäänkirjautumista, kirjautumista ja uloskirjautumista. Se välittää käyttäjänimen ja salasanan tiedot kirjautumis- ja kirjautumislomakkeista RestrictedController
palvelu, joka lähettää HTTP-pyynnöt taustajärjestelmälle. Sitten se tallentaa tunnuksen paikalliselle tallennustilalle tai näyttää virheilmoituksen, riippuen taustajärjestelmän vastauksesta.
getRestrictedData
getApiData
käyttäytyy samalla tavalla, vain se hakee tiedot käyttämällä Data
ja .controller('RestrictedController', ['$rootScope', '$scope', 'Data', function ($rootScope, $scope, Data) { Data.getRestrictedData(function (res) { $scope.data = res.data; }, function () { $rootScope.error = 'Failed to fetch restricted content.'; }); Data.getApiData(function (res) { $scope.api = res.data; }, function () { $rootScope.error = 'Failed to fetch restricted API content.'; }); }]);
toimii Authorization
palvelu.
tokenClaims
Taustajärjestelmä on vastuussa rajoitettujen tietojen toimittamisesta vain, jos käyttäjä on todennettu. Tämä tarkoittaa, että vastaamiseksi rajoitetuilla tiedoilla näiden pyyntöjen on sisällettävä kelvollinen JWT sen sisällä getTokenClaims
otsikko tai kyselymerkkijono. Jos näin ei ole, palvelin vastaa 401 luvattomalla virhetilakoodilla.
Todennuspalvelu
Todennuspalvelu on vastuussa sisäänkirjautumisesta ja HTTP-pyyntöjen kirjautumisesta taustajärjestelmään. Jos pyyntö onnistuu, vastaus sisältää allekirjoitetun tunnuksen, joka sitten dekoodataan base64, ja mukana olevat tunnuksen vaatimustiedot tallennetaan angular.module('app') .factory('Auth', ['$http', '$localStorage', 'urls', function ($http, $localStorage, urls) { function urlBase64Decode(str) { var output = str.replace('-', '+').replace('_', '/'); switch (output.length % 4) { case 0: break; case 2: output += '=='; break; case 3: output += '='; break; default: throw 'Illegal base64url string!'; } return window.atob(output); } function getClaimsFromToken() { var token = $localStorage.token; var user = {}; if (typeof token !== 'undefined') { var encoded = token.split('.')[1]; user = JSON.parse(urlBase64Decode(encoded)); } return user; } var tokenClaims = getClaimsFromToken(); return { signup: function (data, success, error) { $http.post(urls.BASE + '/signup', data).success(success).error(error) }, signin: function (data, success, error) { $http.post(urls.BASE + '/signin', data).success(success).error(error) }, logout: function (success) { tokenClaims = {}; delete $localStorage.token; success(); }, getTokenClaims: function () { return tokenClaims; } }; } ]);
muuttuja. Tämä välitetään ohjaimelle angular.module('app') .factory('Data', ['$http', 'urls', function ($http, urls) { return { getRestrictedData: function (success, error) { $http.get(urls.BASE + '/restricted').success(success).error(error) }, getApiData: function (success, error) { $http.get(urls.BASE_API + '/restricted').success(success).error(error) } }; } ]);
-palvelun kautta toiminto.
|_+_|
Datapalvelu
Tämä on yksinkertainen palvelu, joka pyytää todennuspalvelimelle sekä API-palvelimelle joitakin rajoitettuja tietoja. Se tekee pyynnön ja siirtää onnistumisen ja virheiden takaisinkutsut ohjaimelle.
|_+_|
Tunnuspohjainen todennus antaa meille mahdollisuuden rakentaa irrotettuja järjestelmiä, jotka eivät ole sidoksissa tiettyyn todennusjärjestelmään. Tunnus voidaan luoda missä tahansa ja kuluttaa missä tahansa järjestelmässä, joka käyttää samaa salaista avainta tunnuksen allekirjoittamiseen. Ne ovat mobiilivalmiita eivätkä vaadi meitä käyttämään evästeitä.
JSON-verkkotunnukset toimivat kaikilla suosituilla ohjelmointikielillä ja ovat nopeasti saamassa suosiotaan. Niitä tukevat yritykset, kuten Google, Microsoft ja Zendesk. Heidän Internet-suunnittelutyöryhmänsä (IETF) vakiomäärittely on edelleen luonnoksessa ja saattaa muuttua hieman tulevaisuudessa.
JWT: stä on vielä paljon katettavaa, kuten kuinka käsitellä turvallisuus yksityiskohdat ja virkistävät tunnukset, kun ne vanhenevat, mutta JSON Web Token -oppaassa tulisi osoittaa JWT: n käytön peruskäyttö ja mikä tärkeämpää, edut.
Tämä viittaa JWT: hen, joka välitetään HTTP-otsikon kautta nimeltä Valtuutus merkkijonomuodossa 'Bearer $ your_token_here'.
JWT on lyhenne sanoista JSON Web Token, joka on yleinen todennustaktiikka, jota käytetään nykyaikaisissa verkkosovelluksissa.
JSON on yksinkertaisesti datamuoto, joka muistuttaa läheisesti JavaScriptien sallimaa kirjaimellista muotoa. Se on hierarkkinen muoto, joka sallii sisäkkäisiä objekteja ja taulukoita sekä merkkijono- ja numerolitraaleja.