Dengan Navigation Guards yang ada di vue router, kita bisa melindungi atau menjaga route yang kita miliki apakah harus melewati autentikasi atau dengan syarat tertentu untuk dapat membukanya atau menuju ke suatu halaman.
Untuk contoh dan cara penggunaannya, mari kita membuatnya.
Instalasi Laravel, Membuat Database dan Tabel
Kita siapkan projek terlebih dahulu. Kita mulai dari instalasi laravel, membuat database dan tabel.
laravel new lavue-app
Silahkan buat database MySQL baru dan hubungkan dengan aplikasi.
//.env DB_DATABASE=lavue_app DB_USERNAME=root DB_PASSWORD=
Kemudian jalankan perintah migrasi.
php artisan migrate
MariaDB [lavue_app]> show tables; +-------------------------+ | Tables_in_newlavueroles | +-------------------------+ | failed_jobs | | migrations | | password_resets | | users | +-------------------------+
Konfigurasi Vue dan Vue Router
Kita lanjutkan untuk proses instalasi vue, mengatur vue instance dan membuat route dengan vue router.
npm install
npm install vue vue-loader vue-template-compiler --save-dev
npm install vue-router
Buka resources > app.js, buat seperti dibawah ini.
require('./bootstrap'); import Vue from 'vue'; import VueRouter from 'vue-router' Vue.use(VueRouter) import App from './components/App.vue' import Home from './components/Home.vue' import Dashboard from './components/Dashboard.vue' const router = new VueRouter({ mode: 'history', routes: [ { path: '/', name: 'home', component: Home }, { path: '/dashboard', name: 'dashboard', component: Dashboard, } ], }) new Vue({ el: '#app', components: { App }, router, });
Silahkan buat folder baru di direktori js dengan nama components dan tambahkan didalamnya file App.vue, Home.vue, dan Dashboard.vue.
//App.vue <template> <div> <router-link :to="{name: 'home'}" >Home</router-link> <router-link :to="{name: 'dashboard'}">Dashboard</router-link> <div class="container"> <router-view></router-view> </div> </div> </template>
//Home.vue <template> <div> Home </div> </template>
//Dashboard.vue <template> <div> Dashboard </div> </template>
Selanjutnya buka file welcome.blade.php, ubah html yang ada dengan dibawah ini.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{csrf_token()}}"> <title>Lavue</title> <style>body{padding:2rem}.container{margin-top:2rem}</style> </head> <body> <div id="app"> <app></app> </div> <script src="{{ mix('js/app.js') }}"></script> </body> </html>
Ubah route di web.php dengan dibawah ini.
Route::get('/{any}', function(){ return view('welcome'); })->where('any', '.*');
Terakhir buka file webpack.mix.js, tambahkan .vue()
seperti dibawah ini untuk memeriksa dan menginstall depedensi atau plugin babel secara otomatis jika ada yang diperlukan.
mix.js('resources/js/app.js', 'public/js').vue();
Kemudian lakukan compiling.
npm run dev
Setelah selesai mari kita jalankan aplikasi pada browser.
php artisan serve
Vue Router sudah terinstal dan siap digunakan.
Penggunaan Navigation Guards
Sekarang mari kita coba menggunakan navigation guards. Kita akan menggunakan router.beforeEach
untuk guard asinkron, dan setiap guard memiliki parameter seperti dibawah ini untuk menerima argument.
router.beforeEach((to, from, next) => { // ... })
- to : Untuk memilih target objek route atau properti dari objek route.
- from : Untuk memilih objek route route yang sedang aktif.
- next : Perintah selanjutnya untuk tugas yang harus diselesaikan.
Objek route bisa dilihat pada gambar di atas atau lihat sendiri dengan vue devtools.
Kita coba buat fungsi pengalihan yang sederhana dulu untuk mencobanya. Silahkan tambahkan dibawah ini pada file app.js, letakan diatas vue instance.
... router.beforeEach((to, from, next) => { if (to.name !== 'home') next({ name: 'home' }) else next() }) ...
Kembali kita compile. Gunakan npm run watch
untuk compiling setiap ada perubahan file js, dan jalankan php artisan serve
di tab baru.
Silahkan coba buka http://localhost:8000/dashboard
. Selain route 'home' kita tidak bisa mengaksesnya.
Login User
Contoh penggunaan lainnya untuk sistem login pengguna. Mari kita buat metode login user dan menggunakan token JWT.
Kita tambahkan user terlebih dahulu menggunakan seeder.
php artisan make:seeder UserSeeder
Buka file UserSeeder.php dan buat buat seperti dibawah ini.
<?php namespace Database\Seeders; use Illuminate\Database\Seeder; use App\Models\User; class UserSeeder extends Seeder { public function run() { $user = new User; $user->name = "user"; $user->email = "[email protected]"; $user->password = bcrypt('12345678'); $user->save(); } }
Lalu tambahkan class seeder di file DatabaseSeeder.php di dalam run()
method seperti dibawah ini.
public function run() { $this->call([ UserSeeder::class ]); }
Kemudian lakukan seeding.
php artisan db:seed
Kita akan login dengan email [email protected]
dan password 12345678
.
Instalasi JWT
Kita lanjutnya untuk instalasi dan konfigurasi JWT. Jalankan pertinah dibawah ini secara berututan.
composer require tymon/jwt-auth:dev-develop --prefer-source php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider" php artisan jwt:secret
Kemudian buka model User.php dan tambahkan implements JWTSubject
, getJWTIdentifier()
, dan getJWTCustomClaims()
seperti dibawah ini.
<?php namespace App\Models; use Tymon\JWTAuth\Contracts\JWTSubject; ... class User extends Authenticatable implements JWTSubject { use HasFactory, Notifiable; ... public function getJWTIdentifier() { return $this->getKey(); } public function getJWTCustomClaims() { return []; } }
Metode Login
Selanjutnya kita buat sebuah controller baru.
php artisan make:controller UserController
Buka UserController.php, buat seperti dibawah ini.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use JWTAuth; class UserController extends Controller { public function login(Request $request) { $credentials = $request->only('email', 'password'); if (auth()->attempt($credentials)) { $response = [ 'user' => auth()->user(), 'token' => JWTAuth::fromUser(auth()->user()) ]; } return response()->json($response); } }
Lalu tambahkan route dibawah ini pada api.php.
Route::post('login', [\App\Http\Controllers\UserController::class, 'login']);
Login Component
Silahkan buat component Login.vue, kemudian import dan tambahkan route link.
//Login.vue <template> <div> <form @submit.prevent="loginForm"> <input type="email" v-model="email" placeholder="email" required> <input type="password" v-model="password" placeholder="password" required> <button type="submit">Login</button> </form> </div> </template> <script> export default { data(){ return { email: "", password: "", } }, methods : { loginForm() { axios.post('api/login', { email: this.email, password: this.password }) .then(response => { localStorage.setItem('user',JSON.stringify(response.data.user)) localStorage.setItem('token',response.data.token) this.$router.push('dashboard') }) .catch(error => { console.error(error); }); } } } </script>
Kita lihat metode loginForm()
di atas. Ketika kita berhasil login, kita simpan respon berupa token dan objek user ke local storage browser untuk kita akses dikemudian.
Selanjutnya silahkan import component Login.vue di app.js dan tambahkan juga link navigasi.
//app.js import Login from './components/Login.vue' { path: '/login', name: 'login', component: Login, }
//App.vue <router-link :to="{name: 'login'}">Login</router-link>
Setelah itu kembali ke app.js, ubah guard yang ada dengan dibawah ini.
router.beforeEach((to, from, next) => { let token = localStorage.getItem('token') != null; if (to.name === 'login' && token){ next({ name: 'home' }) }else if(to.matched.some(record => record.meta.requiresAuth)) { if (!token) { next({ path: '/login', query: { redirect: to.fullPath } }) } else { next() } }else { next() } })
Jadi data token yang kita simpan pada local storage tadi kita akses pada guard yang akan menunda route untuk dilakukan pengecekan apakah token tersedia atau tidak.
Lalu meta
requiresAuth (kita bisa buat dengan nama apa saja) yang ditambahkan adalah untuk menjaga akses route atau url.
Pada route dashboard tambahkan properti meta
seperti di bawah ini.
{ path: '/dashboard', name: 'dashboard', component: Dashboard, meta: { requiresAuth: true, } },
Terakhir, buka component Dashboard.vue dan buat seperti dibawah ini. Kita ambil objek user dari local storage untuk ditampilkan pada dom.
<template> <div> <p>name: {{user.name}}</p> <p>email: {{user.email}} </p> </div> </template> <script> export default { data(){ return { user : JSON.parse(localStorage.getItem('user')) } } } </script>
Sekarang tinggal mencobanya. Silahkan buka route / url yang ada dengan login atau tanpa login.
Logout
Untuk logout, kita tinggal kosongkan local storage dengan membuat metode seperti dibawah ini.
//App.vue <template> <div> <router-link :to="{name: 'home'}" >Home</router-link> <router-link :to="{name: 'dashboard'}">Dashboard</router-link> <router-link :to="{name: 'login'}" v-if="!loggedIn">Login</router-link> <a v-if="loggedIn" @click="logout">Logout</a> <div class="container"> <router-view @setToken="userToken"></router-view> </div> </div> </template> <script> export default { data(){ return { loggedIn : false } }, mounted() { this.userToken() }, methods : { userToken() { this.loggedIn = localStorage.getItem('token') != null }, logout(){ localStorage.removeItem('token') localStorage.removeItem('user') this.userToken() this.$router.push('/') } } } </script>
Buka Login.vue, tambahkan emit seperti dibawah ini untuk transfer data setalah login agar reaktif.
.then(response => { this.$emit('setToken') })
Selesai. Kita sampai disini. Silahkan dicoba, dikembangkan, dan lakukan eksperimen.