Med den økende populariteten til applikasjoner med én side, mobilapplikasjoner og RESTful API-tjenester, veien webutviklere skrive back-end kode har endret seg betydelig. Med teknologier som AngularJS og BackboneJS bruker vi ikke lenger mye tid på å bygge markering, i stedet bygger vi APIer som våre front-end-applikasjoner bruker. Vår back-end handler mer om forretningslogikk og data, mens presentasjonslogikk flyttes utelukkende til front-end eller mobile applikasjoner. Disse endringene har ført til nye måter å implementere autentisering i moderne applikasjoner på.
Autentisering er en av de viktigste delene av en hvilken som helst webapplikasjon. I flere tiår var informasjonskapsler og serverbasert autentisering den enkleste løsningen. Imidlertid kan håndtering av autentisering i moderne mobil- og enkeltsideapplikasjoner være vanskelig, og kreve en bedre tilnærming. De mest kjente løsningene på autentiseringsproblemer for APIer er OAuth 2.0 og JSON Web Token (JWT).
Før vi går inn i denne JSON Web Token-opplæringen, hva er egentlig en JWT?
Et JSON Web Token brukes til å sende informasjon som kan verifiseres og klareres ved hjelp av en digital signatur. Den består av et kompakt og URL-sikkert JSON-objekt, som er kryptografisk signert for å verifisere ektheten, og som også kan krypteres hvis nyttelasten inneholder sensitiv informasjon.
På grunn av sin kompakte struktur brukes JWT vanligvis i HTTP Authorization
overskrifter eller URL-spørsmålsparametere.
En JWT er representert som en sekvens av base64url kodede verdier som er atskilt med punkttegn.
Her er et JWT-tokeneksempel:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJpc3MiOiJ0b3B0YWwuY29tIiwiZXhwIjoxNDI2NDIwODAwLCJodHRwOi8vdG9wdGFsLmNvbS9qd3RfY2xhaW1zL2lzX2FkbWluIjp0cnVlLCJjb21wYW55IjoiVG9wdGFsIiwiYXdlc29tZSI6dHJ1ZX0. yRQYnWzskCZUxPwaQupWkiUzKELZ49eM7oWxAQK_ZXw
Overskriften inneholder metadata for tokenet og inneholder minimalt typen signatur og krypteringsalgoritmen. (Du kan bruke en JSON formater verktøy for å prettifisere JSON-objektet.)
Eksempel på topptekst
{ 'alg': 'HS256', 'typ': 'JWT' }
Denne overskriften på JWT-eksemplet erklærer at det kodede objektet er et JSON Web Token, og at det er signert ved hjelp av HMAC SHA-256-algoritmen.
Når dette er base64-kodet, har vi den første delen av vår JWT.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
I sammenheng med JWT kan et krav defineres som en uttalelse om en enhet (vanligvis brukeren), samt tilleggsmetadata om selve tokenet. Kravet inneholder informasjonen vi vil overføre, og som serveren kan bruke til å håndtere JSON Web Token-autentisering riktig. Det er flere krav vi kan gi; disse inkluderer registrerte kravnavn, offentlige kravnavn og private kravnavn.
Registrerte JWT-krav
Dette er påstandene som er registrert i IANA JSON Web Token Kravregister . Disse JWT-påstandene er ikke ment å være obligatoriske, men snarere å gi et utgangspunkt for et sett med nyttige, interoperable krav.
Disse inkluderer:
Offentlige krav
Offentlige krav må ha kollisjonsbestandige navn. Ved å gjøre navnet til URI eller URN unngås navngivningskollisjoner for JWT-er der avsender og mottaker ikke er en del av et lukket nettverk.
Et eksempel på et offentlig kravnavn kan være: https://www.toptal.com/jwt_claims/is_admin
, og den beste fremgangsmåten er å plassere en fil på det stedet som beskriver kravet, slik at det kan refereres til for dokumentasjon.
Private krav
Private kravnavn kan brukes på steder der JWT bare byttes i et lukket miljø mellom kjente systemer, for eksempel i en bedrift. Dette er påstander som vi kan definere oss selv, som bruker-ID-er, brukerroller eller annen informasjon.
Bruk av kravnavn som kan ha motstridende semantiske betydninger utenfor et lukket eller privat system er utsatt for kollisjon, så bruk dem med forsiktighet.
Det er viktig å merke seg at vi ønsker å holde et web-token så lite som mulig, så bruk bare nødvendige data i offentlige og private krav.
JWT Eksempel Nyttelast
{ 'iss': 'toptal.com', 'exp': 1426420800, 'https://www.toptal.com/jwt_claims/is_admin': true, 'company': 'ApeeScape', 'awesome': true }
Dette eksemplet nyttelast har to registrerte krav, ett offentlig krav og to private krav. Når det er base64-kodet, har vi den andre delen av vår JWT.
eyJpc3MiOiJ0b3B0YWwuY29tIiwiZXhwIjoxNDI2NDIwODAwLCJodHRwOi8vdG9wdGFsLmNvbS9qd3RfY2xhaW1zL2lzX2FkbWluIjp0cnVlLCJjb21wYW55IjoiVG9wdGFsIiwiYXdlc29tZSI6dHJ1ZX0
JWT-standarden følger JSON Web Signature (JWS) spesifikasjonen for å generere det endelige signerte tokenet. Den genereres ved å kombinere den kodede JWT-overskriften og den kodede JWT-nyttelasten, og signere den ved hjelp av en sterk krypteringsalgoritme, for eksempel HMAC SHA-256. Signaturens hemmelige nøkkel holdes av serveren, slik at den kan bekrefte eksisterende tokens og signere nye.
$encodedContent = base64UrlEncode(header) + '.' + base64UrlEncode(payload); $signature = hashHmacSHA256($encodedContent);
Dette gir oss den siste delen av vår JWT.
yRQYnWzskCZUxPwaQupWkiUzKELZ49eM7oWxAQK_ZXw
Det er viktig å bruke TLS / SSL i forbindelse med JWT, for å forhindre menneske-i-midten-angrep. I de fleste tilfeller vil dette være tilstrekkelig til å kryptere JWT-nyttelasten hvis den inneholder sensitiv informasjon. Imidlertid, hvis vi vil legge til et ekstra beskyttelseslag, kan vi kryptere selve JWT-nyttelasten ved hjelp av JSON Web Encryption (PLAY) spesifikasjon.
Selvfølgelig, hvis vi vil unngå ekstra omkostninger ved bruk av JWE, er et annet alternativ å bare beholde sensitiv informasjon i databasen vår, og bruke tokenet vårt for flere API-anrop til serveren når vi trenger tilgang til sensitive data.
Før vi kan se alle fordelene ved å bruke JWT-autentisering, må vi se på hvordan autentisering har blitt gjort tidligere.
Fordi HTTP-protokollen er statsløs, må det være en mekanisme for lagring av brukerinformasjon og en måte å autentisere brukeren på hver etterfølgende forespørsel etter pålogging. De fleste nettsteder bruker informasjonskapsler for å lagre brukerens økt-ID.
Hvordan det fungerer
Nettleseren sender en POST-forespørsel til serveren som inneholder brukerens identifikasjon og passord. Serveren svarer med en informasjonskapsel, som er angitt i brukerens nettleser, og inkluderer en økt-ID for å identifisere brukeren.
Ved hver etterfølgende forespørsel må serveren finne den økten og deserialisere den, fordi brukerdata er lagret på serveren.
Vanskelig å skalere : Serveren må opprette en økt for en bruker og vedvare den et sted på serveren. Dette kan gjøres i minnet eller i en database. Hvis vi har et distribuert system, må vi sørge for at vi bruker en egen øktlagring som ikke er koblet til applikasjonsserveren.
Deling av forespørsel på tvers av opprinnelse (CORS) : Når vi bruker AJAX-anrop for å hente en ressurs fra et annet domene ('kryssopprinnelse'), kan vi komme i problemer med forbudte forespørsler, fordi HTTP-forespørsler som standard ikke inneholder informasjonskapsler på kryssopprinnelsesforespørsler.
Kobling med nettrammen : Når vi bruker serverbasert autentisering, er vi knyttet til rammeverkets autentiseringsskjema. Det er veldig vanskelig, eller til og med umulig, å dele sesjonsdata mellom forskjellige nettrammer skrevet på forskjellige programmeringsspråk.
Tokenbasert / JWT-autentisering er statsløs, så det er ikke nødvendig å lagre brukerinformasjon i økten. Dette gir oss muligheten til å skalere applikasjonen vår uten å bekymre oss for hvor brukeren har logget på. Vi kan enkelt bruke samme token for å hente en sikker ressurs fra et annet domene enn det vi er logget på.
Hvordan JSON Web Tokens fungerer
En nettleser eller mobilklient gjør en forespørsel til godkjenningsserveren som inneholder brukerinnloggingsinformasjon. Autentiseringsserveren genererer et nytt JWT-tilgangstoken og returnerer det til klienten. På hver forespørsel til en begrenset ressurs sender klienten tilgangstokenet i spørringsstrengen eller Authorization
Overskrift. Serveren validerer deretter tokenet og returnerer den sikre ressursen til klienten, hvis den er gyldig.
Autentiseringsserveren kan signere tokenet ved hjelp av en hvilken som helst sikker signaturmetode. For eksempel kan en symmetrisk nøkkelalgoritme som HMAC SHA-256 brukes hvis det er en sikker kanal for å dele den hemmelige nøkkelen mellom alle parter. Alternativt kan et asymmetrisk system med offentlig nøkkel, for eksempel RSA, også brukes, noe som eliminerer behovet for videre nøkkeldeling.
Statsløs, lettere å skalere : Token inneholder all informasjon for å identifisere brukeren, og eliminerer behovet for økttilstand. Hvis vi bruker en lastbalanser, kan vi sende brukeren til hvilken som helst server, i stedet for å være bundet til samme server vi logget på.
Gjenbrukbarhet : Vi kan ha mange separate servere, som kjører på flere plattformer og domener, og bruker det samme token for å autentisere brukeren. Det er enkelt å lage et program som deler tillatelser med et annet program.
JWT-sikkerhet : Siden vi ikke bruker cookies, trenger vi ikke å beskytte mot CSRF-angrep på tvers av nettsteder. Vi bør fortsatt kryptere tokens ved hjelp av JWE hvis vi må legge inn sensitiv informasjon i dem, og overføre tokens over HTTPS for å forhindre menneske-i-midten-angrep.
Opptreden : Det er ingen serversøk for å finne og deserialisere økten på hver forespørsel. Det eneste vi må gjøre er å beregne HMAC SHA-256 for å validere token og analysere innholdet.
I denne JWT-opplæringen skal jeg demonstrere hvordan jeg implementerer den grunnleggende autentiseringen ved hjelp av JSON Web Tokens i to populære webteknologier: Laravel 5 for backend-koden og AngularJS for frontend Single Page Application (SPA) eksempel. (Du finner hele demoen her og kildekoden i dette GitHub-depotet slik at du kan følge opp veiledningen.)
Dette JSON web token-eksemplet vil ikke bruke noen form for kryptering for å sikre konfidensialiteten til informasjonen som overføres i kravene. I praksis er dette ofte greit, fordi TLS / SSL krypterer forespørselen. Imidlertid, hvis token skal inneholde sensitiv informasjon, for eksempel brukerens personnummer, bør den også krypteres med JWE.
Vi vil bruke Laravel til å håndtere brukerregistrering, vedvarende brukerdata til en database og gi noen begrensede data som trenger godkjenning for at Angular-appen skal konsumere. Vi vil lage et eksempel på et API-underdomene for å simulere CORS (Cross-origin resource sharing).
Installasjon og Project Bootstrapping
For å kunne bruke Laravel, må vi installere Komponist pakkeleder på maskinen vår. Når du utvikler deg i Laravel, anbefaler jeg å bruke Laravel Homestead ferdigpakket 'eske' med Vagrant. Det gir oss et komplett utviklingsmiljø uavhengig av operativsystem.
Den enkleste måten å starte vår JWT Laravel-applikasjon på er å bruke en komponistpakke Laravel Installer.
composer global require 'laravel/installer=~1.1'
Nå er vi alle klare til å lage et nytt Laravel-prosjekt ved å kjøre laravel new jwt
.
For spørsmål om denne prosessen henvises til tjenestemannen Laravel dokumentasjon .
Etter at vi har opprettet det grunnleggende Laravel 5-programmet, må vi sette opp Homestead.yaml
, som vil konfigurere mappekartlegging og domenekonfigurasjon for vårt lokale miljø.
Eksempel på Homestead.yaml
fil:
--- 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
Etter at vi har startet opp vår Vagrant-boks med vagrant up
kommandoen og logget på den ved hjelp av vagrant ssh
, navigerer vi til den tidligere definerte prosjektkatalogen. I eksemplet ovenfor vil dette være /home/vagrant/coding/jwt
. Vi kan nå kjøre php artisan migrate
kommando for å lage de nødvendige brukertabellene i databasen vår.
Installere komponistavhengigheter
Heldigvis er det et fellesskap av utviklere som jobber med Laravel og vedlikeholder mange flotte pakker som vi kan gjenbruke og utvide applikasjonen vår med. I dette eksemplet vil vi bruke tymon/jwt-auth
, av Sean Tymon, for håndtering av tokens på serversiden, og barryvdh/laravel-cors
, av Barry vd. Heuvel, for håndtering av CORS.
jwt-auth
Krev tymon/jwt-auth
pakke i vår composer.json
og oppdater avhengighetene våre.
composer require tymon/jwt-auth 0.5.*
Legg til JWTAuthServiceProvider
til vår app/config/app.php
leverandørene.
'TymonJWTAuthProvidersJWTAuthServiceProvider'
Deretter i app/config/app.php
filen, under aliases
array, legger vi til JWTAuth
fasade.
'JWTAuth' => 'TymonJWTAuthFacadesJWTAuth'
Til slutt vil vi publisere pakkekonfigurasjonen ved hjelp av følgende kommando: php artisan config: publish tymon / jwt-auth
JSON Web-tokens blir kryptert med en hemmelig nøkkel. Vi kan generere den nøkkelen ved hjelp av php artisan jwt:generate
kommando. Den vil bli plassert inne i config/jwt.php
fil. I produksjonsmiljøet vil vi imidlertid aldri ha passord eller API-nøkler inne i konfigurasjonsfiler. I stedet bør vi plassere dem i servermiljøvariabler og referere dem i konfigurasjonsfilen med env
funksjon. For eksempel:
'secret' => env('JWT_SECRET')
Vi kan finne ut mer om denne pakken og alle konfigurasjonsinnstillingene på Github .
laravel-cors
Krev barryvdh/laravel-cors
pakke i vår composer.json
og oppdater avhengighetene våre.
composer require barryvdh/laravel-cors [email protected]
Legg til CorsServiceProvider
til vår app/config/app.php
leverandørene.
'BarryvdhCorsCorsServiceProvider'
Legg deretter mellomvare til app/Http/Kernel.php
.
'BarryvdhCorsMiddlewareHandleCors'
Publiser konfigurasjonen til en lokal config/cors.php
filen ved hjelp av php artisan vendor:publish
kommando.
Eksempel på cors.php
filkonfigurasjon:
return [ 'defaults' => [ 'supportsCredentials' => false, 'allowedOrigins' => [], 'allowedHeaders' => [], 'allowedMethods' => [], 'exposedHeaders' => [], 'maxAge' => 0, 'hosts' => [], ], 'paths' => [ 'v1/*' => [ 'allowedOrigins' => ['*'], 'allowedHeaders' => ['*'], 'allowedMethods' => ['*'], 'maxAge' => 3600, ], ], ];
Routing og håndtering av HTTP-forespørsler
For korthets skyld vil jeg legge all koden min i rutene.php-filen som er ansvarlig for Laravel-ruting og delegering av forespørsler til kontrollere. Vi oppretter vanligvis dedikerte kontrollere for å håndtere alle HTTP-forespørsler og holder koden modulær og ren.
Vi vil laste inn AngularJS SPA-visningen vår med
Route::get('/', function () { return view('spa'); });
bruker registrering
Når vi lager en POST
forespørsel til /signup
med et brukernavn og passord, vil vi prøve å opprette en ny bruker og lagre den i databasen. Etter at brukeren er opprettet, opprettes en JWT og returneres via JSON-svar.
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')); });
Brukerpålogging
Når vi lager en POST
forespørsel til /signin
med et brukernavn og passord, bekrefter vi at brukeren eksisterer og returnerer en JWT via JSON-svaret.
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')); });
Henter en begrenset ressurs på samme domene
Når brukeren er logget på, kan vi hente den begrensede ressursen. Jeg har opprettet en rute /restricted
som simulerer en ressurs som trenger en autentisert bruker. For å gjøre dette, forespørselen Authorization
header eller spørringsstreng må gi JWT for backend for å bekrefte.
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() ] ]); } ]);
I dette eksemplet bruker jeg jwt-auth
mellomvare levert i jwt-auth
pakke med 'before' => 'jwt-auth'
. Denne mellomvaren brukes til å filtrere forespørselen og validere JWT-tokenet. Hvis token er ugyldig, ikke til stede eller utløpt, vil mellomvare kaste et unntak som vi kan fange.
I Laravel 5 kan vi fange unntak ved å bruke app/Exceptions/Handler.php
fil. Ved hjelp av render
funksjon kan vi lage HTTP-svar basert på kastet unntak.
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); }
Hvis brukeren er autentisert og token er gyldig, kan vi trygt returnere de begrensede dataene til frontend via JSON.
Henter begrensede ressurser fra API-underdomenet
I det neste JSON-webtokeneksemplet tar vi en annen tilnærming for tokenvalidering. I stedet for å bruke jwt-auth
mellomvare, vil vi håndtere unntak manuelt. Når vi lager en POST
forespørsel til en API-server api.jwt.dev/v1/restricted
, vi lager en forespørsel om opprinnelse, og må aktivere CORS på backend. Heldigvis har vi allerede konfigurert CORS i config/cors.php
fil.
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.']; }); });
Vi bruker AngularJS som en front-end, og stoler på API-samtaler til Laravel back-end-autentiseringsserver for brukerautentisering og eksempeldata, pluss API-serveren for eksempeldata med opprinnelse. Når vi går til hjemmesiden til prosjektet vårt, vil backend betjene resources/views/spa.blade.php
visning som vil starte stroppen Angular-applikasjonen.
Her er mappestrukturen til Angular-appen:
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
Bootstrapping the Angular Application
spa.blade.php
inneholder det essensielle som trengs for å kjøre applikasjonen. Vi bruker Twitter Bootstrap til styling, sammen med et tilpasset tema fra Bootswatch . For å få visuell tilbakemelding når du foretar et AJAX-anrop, bruker vi vinkelbelastningsbar skript, som avlytter XHR-forespørsler og oppretter en lastelinje. I topptekstdelen har vi følgende stilark:
ngStorage
Bunnteksten til vår markering inneholder referanser til biblioteker, samt våre tilpassede skript for vinkelmoduler, kontrollere og tjenester.
Authorization
Vi bruker token
bibliotek for AngularJS, for å lagre tokens i nettleserens lokale lagring, slik at vi kan sende det på hver forespørsel via Toggle navigation JWT Angular example
Overskrift.
I produksjonsmiljøet ville vi selvfølgelig minifisere og kombinere alle skriptfilene og stilarkene våre for å forbedre ytelsen.
Jeg har opprettet en navigasjonsfelt ved hjelp av Bootstrap som vil endre synligheten til riktige lenker, avhengig av brukerens påloggingsstatus. Påloggingsstatus bestemmes av tilstedeværelsen av et app.js
variabel i kontrollerens omfang.
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: '/' });
Rute
Vi har en fil som heter HomeController
som er ansvarlig for å konfigurere alle våre frontruter.
RestrictedController
Her kan vi se at vi har definert fire ruter som håndteres av enten Authorization
eller $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); } }; }]);
. Hver rute tilsvarer en delvis HTML-visning. Vi har også definert to konstanter som inneholder URL-er for HTTP-forespørsler til backend.
Be om interceptor
$ Http-tjenesten til AngularJS lar oss kommunisere med backend og komme med HTTP-forespørsler. I vårt tilfelle ønsker vi å fange opp hver HTTP-forespørsel og injisere den med en controllers.js
overskrift som inneholder vår JWT hvis brukeren er autentisert. Vi kan også bruke en interceptor til å lage en global HTTP-feilbehandler. Her er et eksempel på interceptoren vår som injiserer et token hvis det er tilgjengelig i nettleserens lokale lagring.
HomeController
Kontrollere
I RestrictedController
har vi definert to kontrollere for applikasjonen vår: HomeController
og 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(); }])
håndterer påloggings-, påmeldings- og utloggingsfunksjonalitet. Den overfører brukernavnet og passorddataene fra påloggings- og påmeldingsskjemaene til RestrictedController
tjeneste, som sender HTTP-forespørsler til backend. Det lagrer deretter tokenet til lokal lagring, eller viser en feilmelding, avhengig av svaret fra backend.
getRestrictedData
getApiData
oppfører seg på samme måte, bare den henter dataene ved å bruke Data
og .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.'; }); }]);
funksjoner på Authorization
service.
tokenClaims
Bakenden er kun ansvarlig for å betjene de begrensede dataene hvis brukeren er godkjent. Dette betyr at for å kunne svare med de begrensede dataene, må forespørselen om disse dataene inneholde en gyldig JWT i sin getTokenClaims
topptekst eller spørringsstreng. Hvis det ikke er tilfelle, vil serveren svare med en 401 uautorisert feilstatuskode.
Auth-tjeneste
Auth-tjenesten er ansvarlig for å logge på og registrere HTTP-forespørsler til backend. Hvis forespørselen er vellykket, inneholder svaret det signerte tokenet, som deretter blir base64-dekodet, og den vedlagte token-kravinformasjonen lagres i et 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; } }; } ]);
variabel. Dette sendes til kontrolleren via 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) } }; } ]);
funksjon.
|_+_|
Datatjeneste
Dette er en enkel tjeneste som gjør forespørsler til autentiseringsserveren så vel som API-serveren for noen dummybegrensede data. Det gjør forespørselen, og delegerer suksess- og feilanrop til kontrolleren.
|_+_|
Tokenbasert autentisering gjør det mulig for oss å konstruere frakoblede systemer som ikke er knyttet til et bestemt autentiseringsskjema. Tokenet kan genereres hvor som helst og konsumeres på ethvert system som bruker den samme hemmelige nøkkelen for å signere tokenet. De er mobile klare, og krever ikke at vi bruker informasjonskapsler.
JSON Web Tokens fungerer på tvers av alle populære programmeringsspråk og blir raskt i popularitet. De støttes av selskaper som Google, Microsoft og Zendesk. Deres standardspesifikasjon av Internet Engineering Task Force (IETF) er fremdeles i utkastversjonen og kan endre seg litt i fremtiden.
Det er fortsatt mye å dekke om JWT-er, for eksempel hvordan man håndterer sikkerhet detaljer og forfriskende tokens når de utløper, men JSON Web Token-opplæringen bør demonstrere den grunnleggende bruken og, enda viktigere, fordelene ved å bruke JWT.
Dette refererer til en JWT, som sendes videre via HTTP-overskriften kalt Authorization, i strengformatet 'Bearer $ your_token_here'.
JWT står for JSON Web Token, en vanlig autentiseringstaktikk som brukes i moderne webapper.
JSON er ganske enkelt et dataformat som ligner det dataliterte formatet som er tillatt av JavaScript. Det er et hierarkisk format som tillater nestede objekter og matriser, samt streng- og tallbokstaver.