LoginSignup
32
57

More than 3 years have passed since last update.

VueでFirebaseを使いログイン認証が必要な専用ページを作ろう

Last updated at Posted at 2020-03-01

はじめに

今回はVueとVue RouterとFirebaseを用いてログイン認証後の必要ページを作ってみましょう!
前準備の部分が長くなるので、認証後の処理だけを見たい人はこ↓こ↑をクリック

環境

  • Vue.js 2(CLI)
  • Vue Router
  • Firebase
  • Yarn

下準備

まずは新しいプロジェクト作り

4be703b086ad849f77fce01da0fdfc7a.png
マニュアルで作りましたが、Routerが必要なのでインストールされてあれば他のをインストールしていても問題ありません。
この記事では、説明のために最小構成でプロジェクトを作成します。
b5cda66b7fe426d4c00d0d9c9affc9f8.png
次ですが、ここはhistoryモードを使うのでyで。
655d71fb30622b2d19fca7d2eef1fe27.png
この後も数回、環境の設定をどうするか聞かれますが、今回のRoutingには影響しないので好みの設定で大丈夫です。
5197b02c266ef40242a00b41e11d373c.png
無事に作成が完了したら、一度yarn serveを行い、バニラ状態のページを確認しておきましょう!
a34062308900b9e39a4610b3c333a8ef.png

Firebaseをインストール

次にFirebase CLIをインストールしましょう。
Firebase CLI 公式ドキュメント

npm

npmの場合ですと、公式ドキュメントにある通り、

グローバル

npm install -g firebase-tools

ローカル

npm install -D firebase-tools

yarn

yarnを使用している例は公式にはありませんが、いつもの方法でインストールすることは可能です。

グローバル

yarn global add firebase-tools

ローカル

yarn add firebase-tools

正しくインストールされてるか確認

最後に正しくインストールされてるか確認しましょう。

firebase -V

と入力して、バージョン表記が表示されれば正しくインストールされています!
(※2020年2月29日現在では、7.14.0が最新)

Firebaseの設定をする

インストールが無事終えたら、次はインストールしたプロジェクトのFirebaseの設定をします。

Firebase init

このコマンドを打ち込みます。
すると、英語で「初期化を行う手続きを続行してもいいかー?」(意訳)の問が出現し、
その後に、Firebaseのどの機能を使用するか選択する問が現れます。
abbda024bb2d5a0d8345252559651297.png

今回は認証だけをやりたいのですが、少なくとも1つは機能を選択しなければいけないため、Hostingを選択しました。

次にFirebaseのどのプロジェクトを使用するか?を聞かれます。
930f375809aeb1f7a759796d9674947c.png

1つ目の選択肢はすでにFirebase上に存在する既存プロジェクトを使用する
2つ目は新しくプロジェクトを作成する
となっています。
もしプロジェクトを作っていなかったら2を、既存のを使用するなら1を選択しましょう。

この後、選択した機能毎をどう設定するかの問が行われ、
その問に答えた後に、SPA(シングルページアプリケーション)として設定するかの問が行われます。
SPAを使用したいので、これにはyと入力します。

a8f960e01b79f035f9c9ccbe0d5962df.png
Firebaseの初期化の操作が終わり、このように表示されたら無事完了です!

Firebase ConsoleからAPI情報を作成

先にAPI情報などを記載するfirebase.jsを作成しましょう。
srcフォルダ配下に作成します。

firebase.js
import firebase from "firebase";
import "firebase/auth";

const config = {
  apiKey: /**/,
  authDomain: /**/,
  databaseURL: /**/,
  projectId: /**/,
  storageBucket: /**/,
  messagingSenderId: /**/,
  appId: /**/,
  measurementId: /**/
};

firebase.initializeApp(config);

export default firebase;

configの中の情報は、Firebase Consoleのプロジェクト設定から取得してきましょう。

firebase/authをImportすることで、Firebaseの認証機能を使えるようにImportしています。
これらは必ず行うようにしましょう。

これで下準備は完了です!
次から実際に作成していきましょう!

必要なコンポーネントを作ろう

ルーティングや認証を行う処理などを作る前に、先に必要なコンポーネントを作ります。
必要なコンポーネントは、

  • 登録(sing up)
  • ログイン(sing in)
  • ログアウト(sing out)
  • 認証専用ページ

の4つになるので、これらを作っていきましょう。
サイトトップは初期作成で作られたコンポーネントをそのまま使ってしまいましょう。

コンポーネントを作成

先程必要になる4つのコンポーネントを作っていきましょう。

  • 登録(sing up)
  • ログイン(sing in)
  • ログアウト(sing out)

の3つはコンポーネントは、Firebaseとの通信が必要になるため、
先ほど作っておいたAPI情報を含め初期化しておいたfirebase.jsをImportしておきましょう。
そうしないと、Firebaseの機能を使うことができません。

登録(sing up)

singup.vue
<template>
  <div>
    <h1>SING UP</h1>
    <div>
      <h3>E-mail</h3>
      <input type="text" placeholder="E-mail" v-model="email" />
    </div>
    <div>
      <h3>Password</h3>
      <input type="text" placeholder="Password" v-model="password" />
    </div>
    <button @click="createUserAccount">Sing UP!!</button>
  </div>
</template>

<script>
import firebase from "../firebase.js";
export default {
  name: "singup",
  data() {
    return {
      email: "",
      password: ""
    };
  }
};
</script>

ログイン(sing in)

singin.vue
<template>
  <div>
    <h1>SING IN</h1>
    <div>
      <h3>E-mail</h3>
      <input type="text" placeholder="E-mail" v-model="email" />
    </div>
    <div>
      <h3>Password</h3>
      <input type="text" placeholder="Password" v-model="password" />
    </div>
    <button @click="userSingIn">Sing in Now!!</button>
  </div>
</template>

<script>
import firebase from "../firebase.js";
export default {
  name: "singin",
  data() {
    return {
      email: "",
      password: ""
    };
  }
};
</script>

ログアウト(sing out)

singout.vue
<template>
  <div>
    <h1>SING OUT</h1>
    <button @click="singout">Sing out Now!!</button>
  </div>
</template>

<script>
import firebase from "../firebase.js";
export default {
  name: "singout"
};
</script>

認証専用ページ

mypage.vue
<template>
  <div>
    <h1>SING OUT</h1>
    <p>My Page!!<p>
  </div>
</template>

<script>
export default {
  name: "mypage"
};
</script>

ルーティング

次に作成したコンポーネントを合わせてルートレコードを設定していきましょう

ルートファイルを設定

router.js
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
/*ここから新規追加*/
import Singup from "../components/singup.vue";
import Singin from "../components/singin.vue";
import Singout from "../components/singout.vue";
import Mypage from "../components/mypage.vue";
/*ここまで*/

Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "home",
    component: Home
  },
  {
    path: "/about",
    name: "About",
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () =>
      import(/* webpackChunkName: "about" */ "../views/About.vue")
  },
  /*ここから新規追加*/
  {
    path: "/singup",
    name: "singup",
    component: Singup
  },
  {
    path: "/singin",
    name: "singin",
    component: Singin
  },
  {
    path: "/singout",
    name: "singout",
    component: Singout
  },
  {
    path: "/mypage",
    name: "mypage",
    component: Mypage
  }
  /*ここまで*/
];

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes
});

export default router;

先程作成したコンポーネントをrouter.jsに追加し、ルーティング設定しました。
次に、App.vueの中に作ったコンポーネントへ遷移するためのリンクを設定しましょう。

App.vue
<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link> |
      /*ここから新規追加*/
      <router-link to="/singup">Sing up</router-link> |
      <router-link to="/singin">Sing in</router-link> |
      <router-link to="/singout">Sing out</router-link> |
      <router-link to="/mypage">Mypage</router-link> |
      /*ここまで*/
    </div>
    <router-view />
  </div>
</template>

ここまでのを確認

yarn serveを行い、一旦ここまでの作成段階のを確認しましょう。
e0668afb493addf7c04efaa1a61ce9c7.png
Sing upからMypageまでのリンクを押し、無事ページが遷移したら成功です。

Firebaseを使い認証

FirebaseでE-mailとPasswordで登録できるように設定しよう

認証などの処理を行う前に、Firebase Console画面で、Authenticationの設定を行いましょう。

Authenticationのログイン方法で、メール/パスワードを有効化します。
8ff1cf5ec77c4e7b587ca1546b1a069e.png

02d64008938d5b32fbc3ef791a6c133f.png

メールリンクは今回は有効化しなくてもOKです。
これでメール/パスワードを用いてユーザー登録を行う準備が完了しました。

Firebaseにアカウントを登録しよう

先程作ったSingupコンポーネントに、ユーザーアカウントを追加する処理を組み込みましょう。
Firebaseのユーザーを管理する

singup.vue
<script>
  methods: {
    createUserAccount() {
      firebase
        .auth()
        .createUserWithEmailAndPassword(this.email, this.password)
        .then(() => {
          alert("Create Account");
        })
        .catch(error => {
          alert("Error!", error.message);
          console.error("Account Regeister Error", error.message);
        });
    }
  }
</script>

E-mailPasswordを用いてのよくあるユーザー登録を行うには、
firebase.authcreateUserWithEmailAndPasswordメソッドを使用します。
第一引数にE-mail、第二引数にPasswordを渡してあげると、あとはよしなにやってくれます。
非同期で行うため、結果はthenチェーン内で行う必要があります。
あとは、このメソッドをButtonコンポーネントより呼び出せば登録処理部分は完了です。

ログイン処理をしよう

次はログインを行う処理を追加するために、作っておいたSing inコンポーネントに処理を書き込んでいきましょう。

singin.vue
<script>
  methods: {
    userSingIn() {
      firebase
        .auth()
        .signInWithEmailAndPassword(this.email, this.password)
        .then(() => {
          alert("ログイン成功!");
          this.$router.push("/mypage");
        });
    }
  }
</script>

firebase.authsignInWithEmailAndPasswordメソッドを使い、ログイン処理を行います。
ユーザー登録時と同じ様に、引数にそろぞれE-mailPasswordを渡ししてあげればOKです。
無事ログイン処理が行えたら、thenチェーンで内でRouterpushメソッドを使い、ページを遷移させています。

お試しにログインしてみる

先程作ったユーザ登録画面とログイン画面で、ユーザー登録を行えログインできるか試してみましょう。
ユーザ登録画面で登録が成功とalertが表示され、Firebase Consoleの認証関連のページで、ユーザーが登録されているはずです。
b1a67ca936b76a15b9d4cc8d3fbc95cc.png

ログイン画面で、登録したE-mailPasswordでログインができ、画面がMypageに遷移したらログイン画面も無事作成できています。

ログアウト処理も作ってみる

ログインページが完了したので、次はログアウトページも作っておきましょう。

singout.vue
<script>
  methods: {
    singout() {
      firebase
        .auth()
        .signOut()
        .then(() => {
          alert("Logout!");
        })
        .catch(error => {
          alert(error);
        });
    }
  }
</script>

firebase.authsignOutメソッドを使いログアウト処理を行っています。
ログアウト処理はこれだけで完了です。
ログアウト後にページトップに戻るような動きをつけたい場合には、
ログイン処理時に使った、

this.$router.push();

を使い、pushの引数の中に遷移させたい先のルート名を渡しましょう。

ページにログイン認証を組み込もう

ログイン/ログアウトできるようになりましたが、現状ではログイン時のみしか表示させたくないMypageがログアウト時でも見ることができています。
次は、このMypageをログイン時のみ表示するようにしましょう。
(ようやくここに来て本題に到達)

認証が必要なことの状態をもたせよう

まず、router.jsに認証処理を追加していきましょう。

router.js
  {
    path: "/mypage",
    name: "mypage",
    component: Mypage,
    meta: { requiresAuth: true }
  }

まずは、mypageのルーティング部分にmetaフィールドを追加します。
Vue Router - ルートメタフィールド
metaフィールドに{ requiresAuth: true }のオブジェクトをもたせて、このルートは認証が必要であることの状態をもたせます。
ただし、これだけでは状態を持っているだけなので、ナビゲーションガード、未ログインユーザーがこのページにアクセスしてもページが表示されてしまいます。
別途、ルートガードの処理を作る必要があります。

ナビゲーションガードを実装しよう

Vue Router - ナビゲーションガード
公式にある、router.beforeEachを用いナビゲーションガードを実装してみましょう。
``

router.js
const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes
});

router.beforeEach((to, from, next) => {
  const requiresAuth = to.matched.some(recode => recode.meta.requiresAuth);
  if (requiresAuth) {
    next({ path: "/singin", query: { redirect: to.fullPath } });
  } else {
    next();
  }
});

export default router;

router.beforeEachexport default routerの前に追加しました。
to.matched.some(recode => recode.meta.requiresAuth)で、requiresAuthの状態をもつルートレコードなのかを確認しています。
もし、requiresAuthならnextを用いてsinginへ、そうでないならユーザーが選択したルートレコードへ遷移します。
ただし、この状態ですとログインしているかどうかを確認していないので、mypageへアクセスすると誰でもログインページへ戻ってしまいます。
次は、Firebaseからログイン状態を取得してみましょう。

Firebaseからログイン状態を取得

router.beforeEachの中にログイン状態を取得する方法もありますが、
今回はfirebase.jsに取得処理を書き、処理を分離化させる方法でやってみましょう。
firebase.jsの中に書いていきましょう。

firebase.js
firebase.getCurrentUser = () => {
  return new Promise((resolve, reject) => {
    const unsubscribe = firebase.auth().onAuthStateChanged(user => {
      unsubscribe()
      resolve(user);
    }, reject);
  });
};

Firebase のユーザーを管理する
onAuthStateChangedを用い、ユーザーがログイン状態かを確認できます。
そして、このメソッドがログイン状態になったら即時にその情報を返します。

最後に先程のrouter.beforeEachにこのログイン状態かを確認する処理を追加しましょう。

router.js
const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes
});

router.beforeEach(async (to, from, next) => {
  const requiresAuth = to.matched.some(recode => recode.meta.requiresAuth);
  if (requiresAuth && !(await firebase.getCurrentUser())) {
    next({ path: "/singin", query: { redirect: to.fullPath } });
  } else {
    next();
  }
});

export default router;

await firebase.getCurrentUser()は先程firebase.jsに作成したメソッドとなります。
firebase.getCurrentUser()Promiseの非同期メソッドになるので、
router.beforeEach内の関数にasyncをつけ、これも非同期メソッドとして上げる必要があります。
そして、if文の条件にfirebase.getCurrentUser()を追加しますがこれは!をつけ否定の条件にしておきます。

if (requiresAuth && !(await firebase.getCurrentUser())

そして、2つをand条件にすることで
- 認証が必要なコンポーネント
- ログイン状態でではない

を満たす場合のみに、ログインページへ遷移するようにしました。

最後に無事動作するか確認

最後に、yarn serveを行い、ログインを行ってみてページ遷移するか、
ログアウト状態でMypageへアクセスした場合に、ログイン画面へ戻るかを確認してみましょう。
無事動けば完成です!

おわり

長くなりましたが、今回はFirebaseを用いてVueでのログイン認証が必要なページの作り方を記事にしてみました。
Vueの認証が必要なページの作り方は、Firebaseを使わなくてもrouter.beforeEachの中で処理するのは共通になるので、一度覚えておけば他の認証サービスやAPIを使った場合でも応用は楽にできると思います。

32
57
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
57