HTML5手机APP开发入(5)


HTML5手机APP开发入(5)

回顾一下

HTML5手机APP开发入(4)

如何自定义Componentdirective

HTML5手机APP开发入(3) 如何实现MVC的代码重构,自定义一个Provider Service,Injectable 依赖注入

HTML5手机APP开发入门(2)

利用ionic2 向导生成一个项目并开发一个简单的通讯录的APP

HTML5手机APP开发入门(1) ionic2+angular2 开发环境的配置

内容

完成一个登录验证的功能

这里我要向大家介绍一个第三方提供登录验证的云解决方案的,非常专业。并且支持Angular 2

https://auth0.com

Auth0是一家"身份验证即服务"提供商,旨在为开发人员提供简单易用的身份管理服务。为了保持灵活性和可扩展性,Auth0身份管理平台允许开发人员在身份验证和授权管道中增加自定义代码。而在一个多租户环境中,为了保证不同用户的自定义代码可以互不影响,就需要一种技术提供必要的数据隔离和资源利用保障。

步骤

注册一个auth0账号

登录https://manage.auth0.com/#/

新建一个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提供很多自定开发功能,等有时间了慢慢研究,这里我们先简单的实现吧登录成功后把用户信息保存到本地,这样下次就可以不用在登录了

  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 都有模板不需要另外开发

 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: '',
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实现定位.