Help us understand the problem. What is going on with this article?

Vue.js 2.0 でログイン (vue-router で認証が必要な URL を定義)

More than 1 year has passed since last update.

認証が必要な URL にアクセスした時に、まだログインしていない場合にはログインボタンを表示します。

作成にあたって以下の知識が必要になるので、順に試していきます。

  • コンポーネント
  • vue-router
  • ルートメタフィールド、ナビゲーションガード

Playground として http://codepen.io を使用します。できあがったコードは http://codepen.io/takatama/pen/zoNeWP です。
Vue.js 2.0.7 と vue-router 2.0.2 で動作を確認しました。

なお、Vue.jsについて体系的に学ぶには「Vue.js入門」が超絶オススメです。ログイン、ログアウトについても丁寧に解説されています。

コンポーネント

ドキュメントは https://vuejs.org/v2/guide/components.html です。

User コンポーネントを作ります。プロパティとして name を持ちます。

codepen で Settings > JavaScript > Add External JavaScript で https://unpkg.com/vue/dist/vue.js と入力し、Save & Change ボタンを押します。

HTML:

<div id="app">
  <About />
</div>

JavaScript:

var About = { template: '<h1>About</h1>' };

var app = new Vue({
  el: '#app',
  components: {
    'About': About
  },
});

vue-router

ドキュメントは http://router.vuejs.org/ja/essentials/getting-started.html です。

Dashboard コンポーネントを追加します。/about に About コンポーネント、/dashboard に Dashboard コンポーネントをそれぞれ登録します。

Settings > JavaScript > Add External JavaScript で
https://unpkg.com/vue-router/dist/vue-router.js を追加入力し、Save & Change ボタンを押します。

HTML:

<div id="app">
  <p>
    <router-link to="/about">About</router-link>
    <router-link to="/dashboard">Dashboard</router-link>
  </p>
  <router-view></router-view>
</div>

JavaScript:

var About = { template: '<h1>About</h1>' };
var Dashboard = { template: '<h1>Dashboard</h1>' };

var routes = [
  { path: '/about', component: About },
  { path: '/dashboard', component: Dashboard }
];

var router = new VueRouter({
  routes
});

var app = new Vue({
  el: '#app',
  router
});

<router-view>\ に選択されたコンポーネントが表示されます。

ログインページ

ドキュメントは

です。

/about は認証不要、/dashboard は認証が必要な URL とします。認証が必要な URL にアクセスし、かつ、まだログインしていない場合にログインボタンを表示します。

HTML (変更なし) :

<div id="app">
  <p>
    <router-link to="/about">About</router-link>
    <router-link to="/dashboard">Dashboard</router-link>
  </p>
  <router-view></router-view>
</div>

JavaScript:

認証処理をする Auth と、Login コンポーネントを追加する。/login に Login コンポーネントを登録します。

/dashboard がログインを要することを meta で定義します。ナビゲーションガード router.beforeEach を使って、ログインが必要で、かつ、未ログインの場合に /login にリダイレクトします。

/login にリダイレクトする際、もともとアクセスしようとしていた URL を query パラメーターに付与します( /login?redirect=/dashbaord )。

var About = { template: '<h1>About</div>' };
var Dashboard = { template: '<h1>Dashboard</h1>' };

var Auth = {
  loggedIn: false,
  login: function() { this.loggedIn = true },
  logout: function() { this.loggedIn = false }  
};

var Login = {
  template: '<input type="submit" value="Login" v-on:click="login">',
  methods: {
    login: function() {
      Auth.login();
      router.push(this.$route.query.redirect);
    }
  }
};

var routes = [
  { path: '/about', component: About },
  { path: '/dashboard', component: Dashboard, meta: { requiresAuth: true }},
  { path: '/login', component: Login }
];

var router = new VueRouter({
  routes
});

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth) && !Auth.loggedIn) {
    next({ path: '/login', query: { redirect: to.fullPath }});
  } else {
    next();
  }
});

var app = new Vue({
  el: '#app',
  router
});

ログアウト

Dashboard コンポーネントに /logout へのリンクを追加します。

JavaScript (主な差分のみ):

var Dashboard = {
  template: '<div><h1>Dashboard</h1><router-link to="/logout">Logout</router-link></div>'
};
var Logout = {
  template: '<input type="submit" value="Logout" v-on:click="logout">',
  methods: {
    logout: function() {
      Auth.logout();
      router.push('/');
    }
  }
};
var routes = [
  { path: '/about', component: About },
  { path: '/dashboard', component: Dashboard, meta: { requiresAuth: true }},
  { path: '/login', component: Login },
  { path: '/logout', component: Logout }
];

補足 (デフォルトで認証を有効にする)

ほとんどの URL で認証を必要とするのであれば、デフォルトで認証を有効にして、認証が不要な URL にだけ isPublic: true を指定する方が安全です。認証が必要な URL に meta を定義し忘れ、誤って一般公開してしまうミスを防ぐことができます。

// 全てのURLで認証を必要とする。isPubilc: true の場合だけ認証不要。
var routes = [
  { path: '/about', component: About, meta: { isPublic: true } },
  { path: '/dashboard', component: Dashboard}, // 認証を必要とする
  { path: '/login', component: Login, meta: { isPublic: true } }
];

var router = new VueRouter({
  routes
});

router.beforeEach((to, from, next) => {
  // isPublic でない場合(=認証が必要な場合)、かつ、ログインしていない場合
  if (to.matched.some(record => !record.meta.isPublic) && !Auth.loggedIn) {
    next({ path: '/login', query: { redirect: to.fullPath }});
  } else {
    next();
  }
});
takatama
東京で働くソフトウェアエンジニアです。
https://twitter.com/takatama_jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away