如何在 Ionic 3 中有效地存储和使用身份验证 [英] How to efficiently store and use Authentication in Ionic 3

查看:25
本文介绍了如何在 Ionic 3 中有效地存储和使用身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发适用于 iOS/Android 的 Ionic (3.4) 应用.我不熟悉身份验证过程或应用程序.

I'm currently developing an Ionic (3.4) app for iOS/Android. I'm not familiar with authentification processes or with applications.

在提供程序中使用 HTTP 请求后,我得到我的对象,即用户.但我完全不知道如何存储或处理它.有哪些好的做法:

After using HTTP request in a provider, I get my object, the user. But I have absolutely no idea how to store it or to deal with it. What are the good practices:

  • 我想只将对象存储在提供程序中并在我拥有的每个页面中调用吗?
  • 我想将它作为一种全局对象存储在应用程序中吗?
  • 或者我想(如下所示)将其作为导航变量从一个页面传输到另一个页面?(我想这不是正确的答案)

最后,应用程序在重新加载/重新启动时将如何反应:如何避免人们一次又一次地填写表单?

And finally, how will the application react on reloading/restarting: how to avoid people to fill the form again and again?

这是我的服务:

@Injectable()
export class UserProvider {
    data = {};
    username: string;
    password: string;

    constructor(private _http: Http) {
        console.log('Hello UserProvider Provider');
    }

    getUser(username:string, password:string){

        let urlSearchParams = new URLSearchParams();
        urlSearchParams.append('username', username);
        urlSearchParams.append('password', password);
        let params = urlSearchParams.toString()

        var headers = new Headers();
        headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

        return this._http
        .post("http://api.minesdedouai.fr/user/login", params, {headers:headers} )
        .map(response => response.json())

    }

}

我知道登录请求应该使用一些令牌,但正如我所说,这是一个小学生的 API,我们不是专业人士,它正在工作.

I'm aware that a login request is supposed to use some token, but as I said, this is a small student's API, we're not pro and it's working.

这是使用服务的方法,在组件(页面)的某处.

And this is the method that uses the service, somewhere in a component (a page).

onLogin(form: NgForm) {
  if (form.valid) {
    this._userProvider.getUser(this.login.username, this.login.password)
    .subscribe((response) => {
      this.user = response;
      console.log("Authentification Success");
      this.navCtrl.push(TabsPage, {user: this.user});
    },
    (error) => {
      if (error.status===403){
        console.log("Wrong User")
      }
      else{
        console.log(error);
      }

    });
  }
}

非常感谢

推荐答案

我将向您展示我如何处理我的 ionic 应用程序上的身份验证.

I will expose you how I deal with authentification on my ionic app.

第一步包括创建您要存储的数据的表示形式.我曾经存储一些用户的信息和一个用于认证的 jwt 令牌.

The first step consists of creating a representation of the data you want to store. I used to store some user's information and a jwt token for the authentification.

user.ts:

export class AuthenticatedUser {
  private _username: string;
  private _id: number;
  private _token: string;

  public static GetNewInstance(): AuthenticatedUser {
    return new AuthenticatedUser(null, null, null)
  }

  public static ParseFromObject(object): AuthenticatedUser {
    const model = AuthenticatedUser.GetNewInstance();

    if (object) {
      model.username = object.username;
      model.id = object.id;
      model.token = object.token;
    }

    return model;
  }

  constructor(username: string, id: number, token: string) {
    this._username = username;
    this._id = id;
    this._token = token;
  }

  get username(): string {
    return this._username;
  }

  set username(value: string) {
    this._username = value;
  }

  get id(): number {
    return this._id;
  }

  set id(value: number) {
    this._id = value;
  }

  get token(): string {
    return this._token;
  }

  set token(value: string) {
    this._token = value;
  }
}

  • GetNewInstance 方法用于返回实例化的AuthenticatedUser 变量.
  • ParseFromObject 方法用于从对象返回AuthenticatedUser.将 api 响应 object 转换为模型非常有用.
    • The GetNewInstance method is used to return an instantiated AuthenticatedUser variable.
    • The ParseFromObject method is used to return an AuthenticatedUser from an object. It's very useful to convert an api response object into a model.
    • 之后我创建了一些服务.第一个是用户服务.我用它来访问我的本地存储中的 AuthenticatedUser.在本地存储中,数据是持久性的,关闭应用时不会被删除.

      After that I create some services. The first one is the UserService. I use it to access my AuthenticatedUser inside my local storage. In the local storage the data are persistence and will not be delete when you close the app.

      user.service.ts:

      export class UsersService {
      
        private _user: Subject<AuthenticatedUser> = new Subject<AuthenticatedUser>();
      
        constructor(private storage: Storage) {}
      
        /* ---------------------------------------------------------------------------------------------------------------- */
        /* Observable use object                                                                                            */
      
        public subscribeToUserService(callback) {
          return this._user.subscribe(callback);
        }
      
        public updateUserService(user: AuthenticatedUser) {
          this._user.next(user);
        }
      
        /* ---------------------------------------------------------------------------------------------------------------- */
        /* User storage management                                                                                          */
      
        /**
         * Write user properties in the local storage.
         *
         * @param user
         * @returns {Promise<AuthenticatedUser>}
         */
        createOnStorage(user: AuthenticatedUser): Promise<AuthenticatedUser> {
          return new Promise((resolve) => {
            this.getOnStorage().then((res) => {
              if (res) {
                this.deleteOnStorage().then(() => {
      
                });
              }
            }).then(() => {
              this.updateUserService(user);
              this.storage.set('user', JSON.stringify(user));
              resolve();
            });
          });
        }
      
        /**
         * Get user properties from local storage.
         *
         * @returns {Promise<AuthenticatedUser>}
         */
        getOnStorage(): Promise<AuthenticatedUser> {
          return new Promise((resolve) => {
            this.updateUserService(JSON.parse(this.storage.get('user')));
            resolve(this.storage.get('user'));
          });
        }
      
        /**
         * Get user properties from local storage.
         *
         * @returns {Promise<AuthenticatedUser>}
         */
        getOnStorageSync() {
          this.updateUserService(JSON.parse(this.storage.get('user')));
          return this.storage.get('user');
        }
      
        /**
         * Update user properties from local storage.
         *
         * @param user
         * @returns {Promise<AuthenticatedUser>}
         */
        updateOnStorage(user: AuthenticatedUser): Promise<AuthenticatedUser> {
          return new Promise((resolve) => {
            resolve(this.storage.get('user'));
          });
        }
      
        /**
         * Delete user properties from local storage.
         *
         * @returns {Promise<AuthenticatedUser>}
         */
        deleteOnStorage(): Promise<AuthenticatedUser> {
          return new Promise((resolve) => {
            this.storage.clear();
            resolve();
          });
        }
      }
      

      第二个服务是ApiService.该服务用于发送不同的 HTTP 方法并处理答案.在此服务中,我们将格式化标头并访问已验证用户的令牌.

      The second service is ApiService. This service is use to send different HTTP methods and handled answers. In this service we will Format the header and access to the authenticatedUser's token.

      @Injectable()
      export class ApiService {
      
        private baseUrl = "https://my.api.co";
        private user: AuthenticatedUser;  
      
      
        /* ---------------------------------------------------------------------------------------------------------------- */
      
        constructor(private userService: UserService, private http: Http) {
           getAuthUser()
        }
      
         private getAuthUser() {
           this.userService.getOnStorage.then(
             (user) => {
               this.user = user;
             });      
         }
      
         /**
         * Get the Json Web Token from the local storage.
         *
         * @returns {RequestOptions}
         */
        private formatHeader(): RequestOptions {
          const headers: Headers = new Headers();
          if (this.user.token) {
            headers.append('Authorization', 'Bearer ' + this.user.token);
          }
          return new RequestOptions({headers});
        }
      
        /**
         * Get the body of an HTTP response.
         *
         * @param res
         * @returns {any|{}}
         */
        private handleBody(res: Response) {
          return res.json() || {};
        }
      
        /**
         * Format the error message of an HTTP response.
         *
         * @param error
         * @returns {any}
         */
        private handleError(error: Response | any) {
          let errorModel: any = {};
      
          if (error instanceof Response) {
            const body = error.json() || '';
            const err = body.error || JSON.stringify(body);
      
            errorModel = { status: error.status, message: `${error.status} - ${err.cause} ` };
          } else {
            errorModel = { status: error.status, message: error.toString()};
          }
          return Observable.throw(errorModel);
        }
        /* ---------------------------------------------------------------------------------------------------------------- */
      
        /**
         * Perform a PUT request.
         *
         * @param url
         * @param auth
         * @param body
         * @returns {Observable<>}
         */
        putRequest(url: string, body: Object, auth: boolean = true): Observable<Object> {
          let header = null;
      
          if (auth) {
            header = ApiService.formatHeader();
          }
          return this.http.put(this.BASE_URL + url, body, header)
            .map(ApiService.handleBody)
            .catch(ApiService.handleError);
        }
      
        /**
         * Perform a POST request.
         *
         * @param url
         * @param auth
         * @param body
         * @returns {Observable<>}
         */
        postRequest(url: string, body: Object, auth: boolean = true): Observable<Object> {
          let header = null;
      
          if (auth) {
            header = ApiService.formatHeader();
          }
          return this.http.post(this.BASE_URL + url, body, header)
            .map(ApiService.handleBody)
            .catch(ApiService.handleError);
        }
      
        /**
         * Perform a HEAD request.
         *
         * @param url
         * @param auth
         * @returns {Observable<>}
         */
        headRequest(url: string, auth: boolean = true): Observable<Object> {
          let header = null;
      
          if (auth) {
            header = ApiService.formatHeader();
          }
          return this.http.head(this.BASE_URL + url, header)
            .map(ApiService.handleBody)
            .catch(ApiService.handleError);
        }
      
        /**
         * Perform a GET request.
         *
         * @param url
         * @param auth
         * @returns {Promise<>}
         */
        getRequest(url: string, auth: boolean = true): Observable<Object> {
          let header = null
      
          if(auth) {
            header = ApiService.formatHeader();
          }
      
          return this.http.get(this.BASE_URL + url, header)
            .map(ApiService.handleBody)
            .catch(ApiService.handleError);
        }
      
        /**
         * Perform a DELETE request.
         *
         * @param url
         * @param auth
         * @returns {Observable<>}
         */
        deleteRequest(url: string, auth: boolean = true): Observable<Object> {
          let header = null;
      
          if (auth) {
            header = ApiService.formatHeader();
          }
          return this.http.delete(this.BASE_URL + url, header)
            .map(ApiService.handleBody)
            .catch(ApiService.handleError);
        }
      

      最后一个服务是AuthService.此服务将发送登录/注销请求.

      And the last service is the AuthService. This service will send login/logout requests.

      auth.service.ts:

      @Injectable()
      export class AuthService {
         private user: AuthenticatedUser;
        /* ---------------------------------------------------------------------------------------------------------------- */
      
        constructor(private userService: userService, private apiService: ApiService) {
        this.getAuthUser();
      }
         getAuthUser() {
           this.userService.getOnStorage().then(
              (user) => {
                this.user = user;
              }
           );
         }
      
        /* ---------------------------------------------------------------------------------------------------------------- */
      
        /**
         * Request an authentication access.
         *
         * @param email the email of the user
         * @param password the password of the user
         * @returns {Promise<any>}
         */
        login(email: string, password: string): Promise<AuthentificatedUser> {
          return new Promise((resolve, reject) => {
            this.apiService.postRequest('/auth', {email: email, password: password})
              .subscribe(
                res => resolve(AuthentificatedUser.ParseFromObject(res)),
                error => reject(<any>error));
          });
        }
      
        /**
         * Logout a user from the authentication process.
         *
         * @returns {Promise<any>}
         */
        logout(): Promise<any> {
          return new Promise((resolve) => {
            this.userService.deleteOnStorage().then(() => {
              resolve();
            });
          });
        }
      
      
        /**
         * Check whether a user is already logged in.
         *
         * @returns {boolean}
         */
        isLoggedIn() {
          if (this.user.token) {
            return true;
          } else {
            return false;
          }
        }
      
        /* ---------------------------------------------------------------------------------------------------------------- */
      }
      

      在您的登录页面中:

      this.authService.login('login', 'password').then(
        (user) => {
          this.userSerivce.createOnStorage(user);
          this.navCtrl.push(HomePage);
        }).catch(
          (err) => {
            //show the error
          }
        );
      

      你必须做的最后一件事是检查用户是否已连接或将用户重定向到登录屏幕.

      The last thing you have to do this to check if a user is connected or redirect the user to the login screen.

      export HomePage() {
        private user: AuthenticatedUser;
      
        constructor(private userService: UserService) {
          this.getAuthUser();
        }
      
        private getAuthUser() {
          this.userService.getOnStorage().then(
            (user) => {
              this.user = user;
      
              if (!this.user.token) {
                this.navCtrl.push(LoginPage)
              }
            }
          );
        }
      }
      

      这篇关于如何在 Ionic 3 中有效地存储和使用身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆