見出し画像

Angular×DRF_SPAのログイン機能でやっていること #372

ログイン機能の流れを学んだので整理しておきます。
フロントエンドはAngular、バックエンドはDRFを使っています。

①IDとパスワードを入力して「ログイン」

最初はもちろんIDとパスワードの入力から始まります。ログインボタンを押下するとAngularのHttpClientのpostメソッドで、バックエンド側にリクエストを送信します。

②バックエンドで認証とトークン生成

バックエンド(DRF)でリクエストを受けたら、IDとパスワードの認証を行います。認証が通ればAPIトークンを生成し、レスポンスとしてフロントエンドに返します。

以下はemailがID代わりになっている実装例です。

class SignIn(APIView):
  def post(self, request):
    serializer = SignInSerializer(data=request.data)
    if not serializer.is_valid():
      return self.__response_400('不正なパラメータが含まれています。')
    email = request.data['email']
    password = request.data['password']
    try:
      user = User.objects.get(email=email)
      if not user:
        return self.__response_400('アカウントが無効です。')
      if not user.check_password(password):
        return self.__response_400('パスワードが間違っています。')
      user.api_token = gen_api_token(user.email, password)
      user.save(update_fields=['api_token'])
      serializer = UserSerializer(user, many=False)
      data = serializer.data
      data['status'] = 'valid'
      return Response(serializer.data)
    except User.DoesNotExist:
      return self.__response_400('メールアドレスまたはパスワードが間違っています。')

gen_api_token()というメソッドでAPIトークンを生成・更新し、フロントエンドに返しています。

③取得したトークンでトップページに遷移

バックエンドから帰ってきたユーザー情報とAPIトークンをフロントで受け取って処理します。先ほどのIDとパスワードをpostリクエストで送信したところからの一連です。

  public doLogin(email: string, password: string): Observable<any> {
    const endPoint = this.environmentService.getAPIEndPoint();
    const path = `${endPoint}/signin`;
    const params = {
      email: email,
      password: password
    };
    return this.httpClient.post(path, params).pipe(
      map((res: any) => {
        this.deleteSession();
        this._user = User.fromJson(res);
        this._apiToken = res.api_token;
        this.cookieService.put('token', this._apiToken);
      })
    );

先にdeleteSession()で古いユーザー情報とAPIトークンを削除し、新たに取得したものを格納します。APIトークンの扱いにはAngularのCookieServiceを活用しています。

これでログイン後の画面に遷移する準備が整いました。

doLoginの呼び出し元コードを以下のようにします。

this.sessionService.doLogin(this.emailFormControl.value, this.passwordFormControl.value).subscribe(
  res => {
    if (this.sessionService.apiToken !== null) {
      this.router.navigateByUrl('path/to/top/page/');
      });
    } else {
      this.isLoginFail = true;
      this.isRequested = false;
    }

細かい部分は省略していますが、とりあえずapiTokenに値が挿入されていればトップページにリダイレクトする仕組みになっています。

トップページに表示するデータを取得する際にHttpClientのgetメソッドを使いますが、そのリクエストヘッダー(X-HTTP-AUTH-TOKEN)に先ほど生成したトークンをセットします。

以下のイメージです。トークンのセットはthis.sessionService.authHeaderで実現しています。

  public getEnterprises(): Promise<Enterprise[]> {
    const endPoint = this.environmentService.getAPIEndPoint();
    const path = `${endPoint}/users/enterprises/`;
    return this.httpClient
      .get(path, this.sessionService.authHeader)
      .pipe(
        map((res: string[]) => {
          return res.map(x => Enterprise.fromJson(x));
        }),
        catchError(error => {
          console.warn(error);
          return observableThrowError('errorだよ');
        })
      )
      .toPromise();

メソッドの中身は以下です。HttpHeaders()はAngularが用意してくれています。

  public get authHeader() {
    const token = this.apiToken ? this.apiToken : 'xx';
    return {
      headers: new HttpHeaders().set('X-HTTP-AUTH-TOKEN', token)
    };


ここまでお読みいただきありがとうございました!

この記事が気に入ったらサポートをしてみませんか?