HTML5手機APP開發入(5)
回顧一下
HTML5手機APP開發入(4)
如何自定義Component,directive
HTML5手機APP開發入(3) 如何實現MVC的程式碼重構,自定義一個Provider Service,Injectable 依賴注入
HTML5手機APP開發入門(2)
利用ionic2 嚮導生成一個專案並開發一個簡單的通訊錄的APP
HTML5手機APP開發入門(1) ionic2+angular2 開發環境的配置
內容
完成一個登入驗證的功能
這裡我要向大家介紹一個第三方提供登入驗證的雲解決方案的,非常專業。並且支援Angular 2
Auth0是一家"身份驗證即服務"提供商,旨在為開發人員提供簡單易用的身份管理服務。為了保持靈活性和可擴充套件性,Auth0身份管理平臺允許開發人員在身份驗證和授權管道中增加自定義程式碼。而在一個多租戶環境中,為了保證不同使用者的自定義程式碼可以互不影響,就需要一種技術提供必要的資料隔離和資源利用保障。
步驟
註冊一個auth0賬號
新建一個application,這裡需要做一些簡單的配置
Allowed Callback URLs 設定你測試的客戶端域名的url
配置auth0 客戶端
Auth0提供了不同環境的Quick Start,我這邊的環境就是ionic 2 + Angular 2
基本上一步一步照著做不會有問題。
1. Add the Auth0 Scripts and Install angular2-jwt
Install angular2-jwt with npm.
Add Lock in your index.html file and set the viewport.
新增javascript引用
2.修改app.ts
這裡需要把用到類庫angular2-jwt引用到專案中。同時還需要把Http也要加進來
注意:
providers:[DataService, provide(AuthHttp, { useFactory: (http) => { return new AuthHttp(new AuthConfig({noJwtError: true}), http); }, deps: [Http] }), AuthService],
3.新建一個authService用來實現登入驗證
新增這些基礎程式碼Quick Start都有提供照抄就可以了
Auth0提供很多自定開發功能,等有時間了慢慢研究,這裡我們先簡單的實現吧登入成功後把使用者資訊儲存到本地,這樣下次就可以不用在登入了
![](https://i.iter01.com/images/86153736c3d440f2e7d2df2432d97112d2ef05f0cb7522cf2307c3de9447249a.gif)
1 import {Storage, LocalStorage} from 'ionic-angular'; 2 import {HTTP_PROVIDERS, Http} from 'angular2/http'; 3 import {Type} from 'angular2/core'; 4 import {AuthHttp, JwtHelper, tokenNotExpired,AuthConfig} from 'angular2-jwt'; 5 import {Injectable} from 'angular2/core'; 6 import {Observable} from 'rxjs/Rx'; 7 8 // Avoid name not found warnings 9 declare var Auth0Lock; 10 11 @Injectable() 12 export class AuthService { 13 jwtHelper: JwtHelper = new JwtHelper(); 14 lock = new Auth0Lock('05VEtQMpSej5rgSgKor4XsaMaCJm8hLa', 'app1001.auth0.com'); 15 local: Storage = new Storage(LocalStorage); 16 refreshSubscription: any; 17 user: Object; 18 19 constructor(private authHttp: AuthHttp) { 20 // If there is a profile saved in local storage 21 this.local.get('profile').then((profile)=>{ 22 if (profile) { 23 this.user = JSON.parse(profile); 24 } 25 }); 26 //let profile = this.local.get('profile').map(); 27 // if (profile) { 28 // this.user = JSON.parse(profile); 29 // } 30 } 31 32 public authenticated() { 33 // Check if there's an unexpired JWT 34 return tokenNotExpired(); 35 } 36 37 public login() { 38 // Show the Auth0 Lock widget 39 this.lock.show({ 40 closable: false, 41 authParams: { 42 scope: 'openid offline_access', 43 device: 'Mobile device' 44 } 45 }, (err, profile, token, accessToken, state, refreshToken) => { 46 if (err) { 47 alert(err); 48 } 49 // If authentication is successful, save the items 50 // in local storage 51 this.local.set('profile', JSON.stringify(profile)); 52 this.local.set('id_token', token); 53 this.local.set('refresh_token', refreshToken); 54 this.user = profile; 55 // Schedule a token refresh 56 this.scheduleRefresh(); 57 }); 58 } 59 60 public logout() { 61 this.local.remove('profile'); 62 this.local.remove('id_token'); 63 this.local.remove('refresh_token'); 64 this.user = null; 65 // Unschedule the token refresh 66 this.unscheduleRefresh(); 67 } 68 69 public scheduleRefresh() { 70 this.authHttp.tokenStream 71 // .flatMap(token=>{ 72 // let jwtIat = this.jwtHelper.decodeToken(token).iat; 73 // let jwtExp = this.jwtHelper.decodeToken(token).exp; 74 // let iat = new Date(0); 75 // let exp = new Date(0); 76 // 77 // let delay = (exp.setUTCSeconds(jwtExp) - iat.setUTCSeconds(jwtIat)); 78 // return Observable.interval(delay); 79 // }) 80 .subscribe( 81 data => { 82 console.log(data) 83 this.getNewJwt(); 84 }, 85 err => console.log(err), 86 () => console.log('Complete') 87 ); 88 89 // If the user is authenticated, use the token stream 90 // provided by angular2-jwt and flatMap the token 91 // let source = this.authHttp.tokenStream.flatMap( 92 // token => { 93 // // The delay to generate in this case is the difference 94 // // between the expiry time and the issued at time 95 // let jwtIat = this.jwtHelper.decodeToken(token).iat; 96 // let jwtExp = this.jwtHelper.decodeToken(token).exp; 97 // let iat = new Date(0); 98 // let exp = new Date(0); 99 // 100 // let delay = (exp.setUTCSeconds(jwtExp) - iat.setUTCSeconds(jwtIat)); 101 // 102 // return Observable.interval(delay); 103 // }); 104 // 105 // this.refreshSubscription = source.subscribe(() => { 106 // this.getNewJwt(); 107 // }); 108 } 109 110 public startupTokenRefresh() { 111 // If the user is authenticated, use the token stream 112 // provided by angular2-jwt and flatMap the token 113 // if (this.authenticated()) { 114 // let source = this.authHttp.tokenStream.flatMap( 115 // token => { 116 // // Get the expiry time to generate 117 // // a delay in milliseconds 118 // let now: number = new Date().valueOf(); 119 // let jwtExp: number = this.jwtHelper.decodeToken(token).exp; 120 // let exp: Date = new Date(0); 121 // exp.setUTCSeconds(jwtExp); 122 // let delay: number = exp.valueOf() - now; 123 // 124 // // Use the delay in a timer to 125 // // run the refresh at the proper time 126 // return Observable.timer(delay); 127 // }); 128 // 129 // // Once the delay time from above is 130 // // reached, get a new JWT and schedule 131 // // additional refreshes 132 // source.subscribe(() => { 133 // this.getNewJwt(); 134 // this.scheduleRefresh(); 135 // }); 136 // } 137 } 138 139 public unscheduleRefresh() { 140 // Unsubscribe fromt the refresh 141 if (this.refreshSubscription) { 142 this.refreshSubscription.unsubscribe(); 143 } 144 } 145 146 public getNewJwt() { 147 this.local.get('refresh_token').then(token=>{ 148 this.lock.getClient().refreshToken(token,(err, delegationRequest) => { 149 if (err) { 150 alert(err); 151 } 152 console.log(delegationRequest); 153 this.local.set('id_token', delegationRequest.id_token); 154 }); 155 }); 156 // Get a new JWT from Auth0 using the refresh token saved 157 // in local storage 158 // let refreshToken = this.local.get('refresh_token')._result; 159 // this.lock.getClient().refreshToken(refreshToken, (err, delegationRequest) => { 160 // if (err) { 161 // alert(err); 162 // } 163 // this.local.set('id_token', delegationRequest.id_token); 164 // }); 165 } 166 }
4.修改app.ts 實現登入後才能訪問
如果沒有登入就顯示登入頁面,而這登入頁面auth0 都有模板不需要另外開發
![](https://i.iter01.com/images/86153736c3d440f2e7d2df2432d97112d2ef05f0cb7522cf2307c3de9447249a.gif)
1 import {App, Platform,Storage, SqlStorage} from 'ionic-angular'; 2 import {StatusBar} from 'ionic-native'; 3 import {ListPage} from './pages/home/list'; 4 import {DataService} from './pages/services/dataService'; 5 import {tokenNotExpired, JwtHelper,AuthHttp, AuthConfig} from 'angular2-jwt'; 6 import {provide} from 'angular2/core'; 7 import {HTTP_PROVIDERS, Http} from 'angular2/http'; 8 import {Type} from 'angular2/core'; 9 import {AuthService} from './pages/services/auth'; 10 11 declare var Auth0Lock; 12 @App({ 13 template: '<ion-nav [root]="rootPage"></ion-nav>', 14 providers:[DataService, 15 provide(AuthHttp, { 16 useFactory: (http) => { 17 return new AuthHttp(new AuthConfig({noJwtError: true}), http); 18 }, 19 deps: [Http] 20 }), 21 AuthService], 22 config: {} // http://ionicframework.com/docs/v2/api/config/Config/ 23 }) 24 export class MyApp { 25 rootPage: any = ListPage; 26 //lock = new Auth0Lock('T1wdQrDposGW5BisaKViC0Cu9CuxtR0c', 'towfeek.eu.auth0.com'); 27 //jwtHelper: JwtHelper = new JwtHelper(); 28 //location: Location; 29 30 constructor(platform: Platform,private authService:AuthService) { 31 //var self = this; 32 platform.ready().then(() => { 33 // Okay, so the platform is ready and our plugins are available. 34 // Here you can do any higher level native things you might need. 35 StatusBar.styleDefault(); 36 if(authService.authenticated()){ 37 this.authService.login(); 38 } 39 40 // this.lock.show((err: string, profile: string, id_token: string) => { 41 // if (err) { 42 // throw new Error(err); 43 // } 44 // 45 // localStorage.setItem('profile', JSON.stringify(profile)); 46 // localStorage.setItem('id_token', id_token); 47 // 48 // console.log( 49 // this.jwtHelper.decodeToken(id_token), 50 // this.jwtHelper.getTokenExpirationDate(id_token), 51 // this.jwtHelper.isTokenExpired(id_token) 52 // ); 53 //}); 54 55 56 }); 57 } 58 }
5.RUN Test
當你執行app的時候系統就第一時間彈出登入頁面,同時還有註冊功能。是不是省了不少工作量
下次準備內容
打算在通訊錄裡呼叫一些手機的功能如何利用cordova-plugin-camera 呼叫拍照功能,利用cordova-plugin-geolocation實現定位.