Med ankomsten av funksjonsrike frontend-rammer som AngularJS, blir mer og mer logikk implementert på front-enden, for eksempel datamanipulering / validering, autentisering og mer. Satellizer, en brukervennlig tokenbasert autentiseringsmodul for AngularJS, forenkler prosessen med å implementere autentiseringsmekanisme i AngularJS. Biblioteket leveres med innebygd støtte for Google, Facebook, LinkedIn, Twitter, Instagram, GitHub, Bitbucket, Yahoo, Twitch og Microsoft (Windows Live) -kontoer.
I denne artikkelen vil vi bygge en veldig enkel webapp som ligner den her som lar deg logge på og se informasjon om gjeldende bruker.
Dette er to skumle ord som du ofte møter når appen din begynner å integrere et brukersystem. I følge Wikipedia:
Godkjenning er handlingen med å bekrefte sannheten til et attributt til et enkelt stykke data (et datum) hevdet sant av en enhet.
Autorisasjon er funksjonen til å spesifisere tilgangsrettigheter til ressurser knyttet til informasjonssikkerhet og datasikkerhet generelt og til tilgangskontroll spesielt.
Når det gjelder lekmann, kan vi ta et eksempel på et blogginnlegg med noen som jobber med det. Bloggerne skriver artikler og lederen validerer innholdet. Hver person kan autentisere (innlogging) i systemet, men rettighetene (autorisasjon) er forskjellige, så bloggeren kan ikke validere innhold mens lederen kan.
Du kan lage ditt eget autentiseringssystem i AngularJS ved å følge noen veiledninger som denne veldig detaljerte: JSON Web Token Tutorial: Et eksempel i Laravel og AngularJS . Jeg foreslår at du leser denne artikkelen ettersom den forklarer JWT (JSON Web Token) veldig bra, og viser en enkel måte å implementere autentisering i AngularJS ved å bruke direkte lokal lagring og HTTP-avlyttere.
Så hvorfor Satellizer? Hovedårsaken er at den støtter en håndfull pålogginger på sosiale nettverk som Facebook, Twitter, etc. I dag, spesielt for nettsteder som brukes på mobil, er det ganske tungvint å skrive brukernavn og passord, og brukere forventer å kunne bruke nettstedet ditt med liten hindring ved å bruke sosiale pålogginger. Siden det er ganske repeterende å integrere SDK for hvert sosiale nettverk og følge dokumentasjonene deres, ville det være fint å støtte disse sosiale påloggingene med minimal innsats.
Videre er Satellizer en aktiv prosjekt på Github. Aktiv er nøkkelen her, da disse SDK-ene endres ganske ofte, og du ikke vil lese dokumentasjonen deres nå og da (alle som jobber med Facebook SDK vet hvor irriterende det er)
Det er her ting begynner å bli interessante.
Vi bygger en webapp som har vanlig innlogging / register (dvs. bruker brukernavn, passord) og som også støtter sosiale pålogginger. Denne webappen er veldig enkel, siden den bare har 3 sider:
For backend bruker vi Python og Flask. Python og rammeverket Flask er ganske uttrykksfulle, så jeg håper å overføre koden til andre språk / rammeverk ikke vil være veldig vanskelig. Vi vil selvfølgelig bruke AngularJS for frontend. Og for sosiale pålogginger vil vi bare integrere med Facebook, da det er det mest populære sosiale nettverket på dette tidspunktet.
La oss begynne!
Slik strukturerer vi koden vår:
- app.py - static/ - index.html - app.js - bower.json - partials/ - login.tpl.html - home.tpl.html - secret.tpl.html
All back-end-koden er inne app.py . Front-end-koden er satt i statisk / mappe. Som standard vil Flask automatisk vise innholdet i statisk / mappe. Alle delvisningene er i statisk / partiell / og håndteres av ui.router-modulen.
For å starte kodingen av backend trenger vi Python 2.7. * Og installerer de nødvendige bibliotekene ved hjelp av pip. Du kan selvfølgelig bruke virtualenv for å isolere et Python-miljø. Nedenfor er listen over nødvendige Python-moduler for å sette i krav.txt:
Flask==0.10.1 PyJWT==1.4.0 Flask-SQLAlchemy==1.0 requests==2.7.0
Slik installerer du alle disse avhengighetene:
pip install -r requirements.txt
I app.py vi har noen innledende kode for å starte flasken (importuttalelser er utelatt for kortfattethet):
app = Flask(__name__) @app.route('/') def index(): return flask.redirect('/static/index.html') if __name__ == '__main__': app.run(debug=True)
Neste vi i det bower og installer AngularJS og ui.router:
bower init # here you will need to answer some question. when in doubt, just hit enter :) bower install angular angular-ui-router --save # install and save these dependencies into bower.json
Når disse bibliotekene er installert, må vi inkludere AngularJS og ui-router i index.html og lag rutinger på 3 sider: hjem, pålogging og hemmelighet.
Home Login Secret
Nedenfor er koden vi trenger i main.js for å konfigurere ruting:
var app = angular.module('DemoApp', ['ui.router']); app.config(function ($stateProvider, $urlRouterProvider) { $stateProvider .state('home', { url: '/home', templateUrl: 'partials/home.tpl.html' }) .state('secret', { url: '/secret', templateUrl: 'partials/secret.tpl.html', }) .state('login', { url: '/login', templateUrl: 'partials/login.tpl.html' }); $urlRouterProvider.otherwise('/home'); });
På dette punktet hvis du kjører serverpython app.py , bør du ha dette grunnleggende grensesnittet på http: // localhost: 5000
Koblingene Hjem, Innlogging og Hemmelighet skal fungere på dette punktet og vise innholdet i de tilsvarende malene.
Gratulerer, du er akkurat ferdig med å sette opp skjelettet! Hvis du støter på noen feil, kan du sjekke ut kode på GitHub
På slutten av dette trinnet har du en webapp som du kan registrere / logge på med e-post og passord.
Det første trinnet er å konfigurere backend. Vi trenger en brukermodell og en måte å generere JWT-token for en gitt bruker. Brukermodellen vist nedenfor er virkelig forenklet og utfører ikke engang noen grunnleggende kontroller som for eksempel felt e-post inneholder “@”, eller hvis felt passord inneholder minst 6 tegn osv.
class User(db.Model): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(100), nullable=False) password = db.Column(db.String(100)) def token(self): payload = { 'sub': self.id, 'iat': datetime.utcnow(), 'exp': datetime.utcnow() + timedelta(days=14) } token = jwt.encode(payload, app.config['TOKEN_SECRET']) return token.decode('unicode_escape')
Vi bruker jwt-modulen i python for å generere nyttelastdelen i JWT. Iat- og exp-delen tilsvarer tidsstempelet som token opprettes og utløper. I denne koden utløper tokenet om to uker.
Etter at brukeren ble opprettet, kan vi legge til 'påloggings' og 'registrer' sluttpunktene. Koden for begge er ganske like, så her vil jeg bare vise 'register' -delen. Vær oppmerksom på at som standard vil Satellizer ringe sluttpunktene / auth / login og / auth / signup for henholdsvis “login” og “register”.
@app.route('/auth/signup', methods=['POST']) def signup(): data = request.json email = data['email'] password = data['password'] user = User(email=email, password=password) db.session.add(user) db.session.commit() return jsonify(token=user.token())
La oss sjekke sluttpunktet ved hjelp av krøll først:
curl localhost:5000/auth/signup -H 'Content-Type: application/json' -X POST -d '{'email':' [email protected] ','password':'xyz'}'
Resultatet skal se slik ut:
{ 'token': 'very long string….' }
Nå som bakenden er klar, la oss angripe fronten! Først må vi installere satellizer og legge den til som en avhengighet i main.js:
bower install satellizer --save
Legg til satellitt som avhengighet:
var app = angular.module('DemoApp', ['ui.router', 'satellizer']);
Innlogging og påmelding i satellizer er faktisk ganske enkel i forhold til alt oppsett til nå:
$scope.signUp = function () { $auth .signup({email: $scope.email, password: $scope.password}) .then(function (response) { // set the token received from server $auth.setToken(response); // go to secret page $state.go('secret'); }) .catch(function (response) { console.log('error response', response); }) };
Hvis du har problemer med å sette opp koden, kan du ta en titt på kode på GitHub .
Ja det er korrekt! Inntil nå kan hvem som helst gå til hemmelig side uten å logge inn.
Det er på tide å legge til noen avlytter i AngularJS for å være sikker på at hvis noen går til hemmelig side, og hvis denne brukeren ikke er innlogget, vil de bli omdirigert til påloggingssiden.
Først bør vi legge til et flagg som kreves Logg på for å skille hemmelig side fra andre.
.state('secret', { url: '/secret', templateUrl: 'partials/secret.tpl.html', controller: 'SecretCtrl', data: {requiredLogin: true} })
'Data' -delen vil bli brukt i $ stateChangeStart-hendelsen som utløses hver gang rutingen endres:
app.run(function ($rootScope, $state, $auth) { $rootScope.$on('$stateChangeStart', function (event, toState) { var requiredLogin = false; // check if this state need login if (toState.data && toState.data.requiredLogin) requiredLogin = true; // if yes and if this user is not logged in, redirect him to login page if (requiredLogin && !$auth.isAuthenticated()) { event.preventDefault(); $state.go('login'); } }); });
Nå kan ikke brukeren gå direkte til den hemmelige siden uten å logge på. Hurra!
Som vanlig kan du finne koden til dette trinnet her .
For øyeblikket er det ikke noe hemmelig på den hemmelige siden. La oss sette noe personlig der.
Dette trinnet starter med å opprette et sluttpunkt i back-enden som bare er tilgjengelig for en autentisert bruker, for eksempel å ha et gyldig token. Endepunktet /bruker nedenfor returnerer bruker-ID og e-post av brukeren som tilsvarer tokenet.
@app.route('/user') def user_info(): # the token is put in the Authorization header if not request.headers.get('Authorization'): return jsonify(error='Authorization header missing'), 401 # this header looks like this: “Authorization: Bearer {token}” token = request.headers.get('Authorization').split()[1] try: payload = jwt.decode(token, app.config['TOKEN_SECRET']) except DecodeError: return jsonify(error='Invalid token'), 401 except ExpiredSignature: return jsonify(error='Expired token'), 401 else: user_id = payload['sub'] user = User.query.filter_by(id=user_id).first() if user is None: return jsonify(error='Should not happen ...'), 500 return jsonify(id=user.id, email=user.email), 200 return jsonify(error='never reach here...'), 500
Igjen bruker vi modulen jwt å dekode JWT-token som er inkludert i overskriften ‘Autorisasjon’ og å håndtere saken når tokenet er utløpt eller ikke gyldig.
La oss teste dette endepunktet ved hjelp av krøll. Først må vi få et gyldig token:
curl localhost:5000/auth/signup -H 'Content-Type: application/json' -X POST -d '{'email':' [email protected] ','password':'xyz'}'
Så med dette token:
curl localhost:5000/user -H 'Authorization: Bearer {put the token here}'
Som gir dette resultatet:
{ 'email': ' [email protected] ', 'id': 1 }
Nå må vi inkludere dette endepunktet i den hemmelige kontrolleren. Dette er ganske enkelt, ettersom vi bare trenger å ringe sluttpunktet ved hjelp av den vanlige $ http-modulen. Token settes automatisk inn i toppteksten av Satellizer, så vi trenger ikke å bry oss med alle detaljene for å lagre tokenet og deretter plassere det i høyre overskrift.
getUserInfo(); function getUserInfo() { $http.get('/user') .then(function (response) { $scope.user = response.data; }) .catch(function (response) { console.log('getUserInfo error', response); }) }
Endelig har vi noe virkelig personlig på den hemmelige siden!
Koden for dette trinnet er på GitHub .
En fin ting med Satellizer, som nevnt i begynnelsen, er at det gjør det enklere å integrere sosial pålogging. På slutten av dette trinnet kan brukerne logge på med sin Facebook-konto!
Den første tingen å gjøre er å lage en applikasjon på Facebook-utvikleresiden for å ha en application_id og en hemmelig kode. Vennligst følg utvikler.facebook.com/docs/apps/register for å opprette en Facebook-utviklerkonto hvis du ikke allerede har en og oppretter en nettsideapp. Etter det vil du ha applikasjons-ID og applikasjonshemmelighet som i skjermbildet nedenfor.
Når brukeren velger å koble til Facebook, vil Satellizer sende en autorisasjonskode til sluttpunktet / auth / facebook . Med denne autorisasjonskoden kan back-enden hente et tilgangstoken fra Facebook / oauth endepunkt som gjør det mulig å ringe til Facebook Graph API for å få brukerinformasjon som plassering, brukervenner, bruker-e-post, etc.
Vi må også holde rede på om det opprettes en brukerkonto med Facebook eller gjennom vanlig registrering. For å gjøre det, legger vi til Facebook ID til vår brukermodell.
facebook_id = db.Column(db.String(100))
Facebook-hemmeligheten konfigureres via env-variabler FACEBOOK_SECRET som vi legger til app.config .
app.config['FACEBOOK_SECRET'] = os.environ.get('FACEBOOK_SECRET')
Så for å starte app.py , bør du sette denne env-variabelen:
FACEBOOK_SECRET={your secret} python app.py
Her er metoden som håndterer Facebook-pålogginger. Som standard vil Satellizer ringe sluttpunktet / auth / facebook .
@app.route('/auth/facebook', methods=['POST']) def auth_facebook(): access_token_url = 'https://graph.facebook.com/v2.3/oauth/access_token' graph_api_url = 'https://graph.facebook.com/v2.5/me?fields=id,email' params = { 'client_id': request.json['clientId'], 'redirect_uri': request.json['redirectUri'], 'client_secret': app.config['FACEBOOK_SECRET'], 'code': request.json['code'] } # Exchange authorization code for access token. r = requests.get(access_token_url, params=params) # use json.loads instead of urlparse.parse_qsl access_token = json.loads(r.text) # Step 2. Retrieve information about the current user. r = requests.get(graph_api_url, params=access_token) profile = json.loads(r.text) # Step 3. Create a new account or return an existing one. user = User.query.filter_by(facebook_id=profile['id']).first() if user: return jsonify(token=user.token()) u = User(facebook_id=profile['id'], email=profile['email']) db.session.add(u) db.session.commit() return jsonify(token=u.token())
For å sende en forespørsel til Facebook-serveren bruker vi de praktiske modulforespørslene. Nå er den vanskelige delen på bakenden ferdig. På front-end er det ganske enkelt å legge til Facebook-pålogging. Først må vi fortelle Satellizer vår Facebook ID ved å legge til denne koden i app.config funksjon:
$authProvider.facebook({ clientId: {your facebook app id}, // by default, the redirect URI is http://localhost:5000 redirectUri: 'http://localhost:5000/static/index.html' });
For å logge på med Facebook kan vi bare ringe:
$auth.authenticate(“facebook”)
Som vanlig kan du sjekke kode på GitHub
På dette tidspunktet er webappen komplett når det gjelder funksjonalitet. Brukeren kan logge på / registrere seg med vanlig e-post og passord eller ved å bruke Facebook. Når brukeren er logget inn, kan den se sin hemmelige side.
Grensesnittet er ikke veldig pent på dette punktet, så la oss legge til litt Bootstrap for oppsettet og den vinklede brødristermodulen for å håndtere en feilmelding pent, for eksempel når innlogging mislykkes.
Koden for denne forskjønende delen finner du her .
Denne artikkelen viser en trinnvis integrering av Satellizer i en (enkel) AngularJS-webapp. Med Satellizer kan vi enkelt legge til andre sosiale pålogginger som Twitter, Linkedin og mer. Koden på fronten er ganske den samme som i artikkelen. Imidlertid varierer back-enden ettersom sosiale nettverks-SDK-er har forskjellige sluttpunkter med forskjellige protokoller. Du kan ta en titt på https://github.com/sahat/satellizer/blob/master/examples/server/python/app.py som inneholder eksempler for Facebook, Github, Google, Linkedin, Twiter og Bitbucket. Når du er i tvil, bør du ta en titt på dokumentasjonen på https://github.com/sahat/satellizer .
I slekt: Ett-klikks pålogging med Blockchain: En MetaMask-opplæring