Pada catatan kali ini akan dibuat sebuah Laravel sebagai server API untuk Login Register dan Logout, dimana klien yang akan menggunakan layanan dari server laravel ini dibuat dengan menggunakan VueJS SPA.
Laravel sudah lebih dulu memudahkan untuk melakukan otentikasi melalui form login konvensional, tapi bagaimana pendaftaran dan Login dengan API? API biasanya menggunakan token untuk mengautentikasi pengguna dan tidak mempertahankan status sesi di antara permintaan. Laravel membuat otentikasi API menjadi ssangat mudah dengan menggunakan Laravel Passport, yang menyediakan implementasi server OAuth2 lengkap untuk aplikasi Laravel Anda dalam hitungan menit.
Bagaimana menggunakan Laravel Passport dan melakukan pendaftaran juga login ikuti langkah-langkahnya pada catatan dibawah ini.
Pertama installasi Laravel
1 |
composer create-project --prefer-dist laravel/laravel mylaravel.test |
Install pasport via composer
1 |
composer require laravel/passport |
Kemudian migrate database
1 |
php artisan migrate |
lalu jalankan passport:install untuk membuat encription key
1 |
php artisan passport:install |
setelah itu buat project vueJS baru
1 |
vue init webpack myvuejs |
install vuex dan axios
1 |
npm install vuex axios --save |
pada Laravel buat sebuah Controller
1 |
php artisan make:controller Api\AuthController |
kemudian pada api router
masukan kode berikut ini
1 2 3 4 5 6 7 8 9 10 |
<?php use Illuminate\Http\Request; Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); }); |
pada .env masukan variabel berikut ini
1 2 3 |
PASSPORT_LOGIN_ENDPOINT="http://mylaravel.test/oauth/token" PASSPORT_CLIENT_ID=2 PASSPORT_CLIENT_SECRET=0Qa9ExR2os6gmP8y1HgqjX3LMmq1u8Q0mm8IkxLw |
dimana PASSPORT_CLIENT_SECRET didapatkan dari table oauth_clients berikut ini:
tambahkan paket guzzlehttp pada laravel
1 |
composer require guzzlehttp/guzzle:~6.0 |
juga tambahkan paket barryvdh/laravel-cors pada laravel
1 |
composer require barryvdh/laravel-cors |
buka file Kernel.php dan masukan \Barryvdh\Cors\HandleCors::class, pada protected middleware
1 2 3 4 5 6 7 8 |
protected $middleware = [ \App\Http\Middleware\CheckForMaintenanceMode::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \App\Http\Middleware\TrustProxies::class, \Barryvdh\Cors\HandleCors::class, ]; |
publish config/cors.php
1 |
php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider" |
buka file config/auth.php dan ganti guards api driver menjadi passport
1 2 3 4 5 6 7 8 9 10 11 |
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ], |
kembali pada vue project, buat sebuah file bernama Signup.vue dan masukan kode berikut ini
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<template> <div class="container"> <div v-if="serverError" class="alert alert-danger" role="alert"> <ul v-for="(value, key) in serverError" :key="key"> <li>{{ value[0] }}</li> </ul> </div> <form @submit.prevent="register"> <div class="form-group"> <label>Name</label> <input type="text" v-model="name" class="form-control" placeholder="Name"> </div> <div class="form-group"> <label>Email</label> <input type="email" v-model="email" class="form-control" placeholder="email"> </div> <div class="form-group"> <label>Password</label> <input type="password" v-model="password" class="form-control" placeholder="Password"> </div> <button type="submit" class="btn btn-primary">Register</button> </form> </div> </template> <script> export default { name: 'Signup', data () { return { email: '', name: '', password: '', serverError: '', successMessage: '' } }, methods: { register() { this.$store.dispatch('register', { name: this.name, email: this.email, password: this.password }) .then(response => { this.successMessage = 'Pendaftaran berhasil, silahkan login' this.$router.push({ name: 'Signin', params: {dataSuccessMessage: this.successMessage} }) }) .catch(error => { this.serverError = Object.values(error.response.data.errors) }) } } } </script> |
dan buat pula file Signin.vue dan masukan kode berikut
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<template> <div class="container"> <div v-if="successMessage" class="alert alert-success" role="alert"> {{successMessage}} </div> <div v-if="serverError" class="alert alert-danger" role="alert"> {{serverError}} </div> <form @submit.prevent="signin"> <div class="form-group"> <label>Email address</label> <input type="email" v-model="email" class="form-control" aria-describedby="emailHelp" placeholder="Enter email"> <small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small> </div> <div class="form-group"> <label>Password</label> <input type="password" v-model="password" class="form-control" placeholder="Password"> </div> <button type="submit" class="btn btn-primary">Login</button> </form> </div> </template> <script> export default { name: 'Signin', props: { dataSuccessMessage: { type: String, } }, data() { return { email: '', password: '', serverError: '', successMessage: this.dataSuccessMessage } }, methods: { signin() { this.$store.dispatch('login', { username: this.email, password: this.password }) .then( response => { this.$router.push({ name: 'Welcome' }) }) .catch(error => { this.serverError = error.response.data this.password = '' this.successMessage = '' }) } } } </script> |
buat juga file Signout.vue dan masukan kode berikut ini
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<template> </template> <script> export default { created() { this.$store.dispatch('logout') .then(response => { this.$router.push('/') }) } } </script> |
isi dari file store adalah sebagai berikut
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
import Vue from 'vue' import Vuex from 'vuex' import axios from 'axios' Vue.use(Vuex) axios.defaults.baseURL = 'http://mylaravel.test/api' export const store = new Vuex.Store({ state: { token: localStorage.getItem('access_token') || null, }, mutations: { setToken(state, token) { state.token = token }, destroyToken(state) { state.token = null }, }, actions: { register(context, data) { return new Promise((resolve, reject) => { axios.post('/register', { name: data.name, email: data.email, password: data.password }) .then(response => { resolve(response) }) .catch(error => { reject(error) }) }) }, login(context, payload) { return new Promise((resolve, reject) => { axios.post('/login', { username: payload.username, password: payload.password, }) .then(response => { const token = response.data.access_token console.log(response.data) localStorage.setItem('access_token', token) context.commit('setToken', token) resolve(response) }) .catch(error => { console.log(error) reject(error) }) }) }, logout(context) { axios.defaults.headers.common['Authorization'] = 'Bearer ' + context.state.token if (context.getters.loggedIn) { return new Promise((resolve, reject) => { axios.post('/logout') .then(response => { localStorage.removeItem('access_token') context.commit('destroyToken') resolve(response) }) .catch(error => { localStorage.removeItem('access_token') context.commit('destroyToken') reject(error) }) }) } }, }, getters: { } }) |
dan juga router sebagai berikut
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import Welcome from '@/components/Welcome' import Signin from '@/components/auth/Signin' import Signup from '@/components/auth/Signup' import Signout from '@/components/auth/Signout' const routes = [ { path: '/', name: 'Welcome', component: Welcome, }, { path: '/signin', name: 'Signin', component: Signin, props: true, }, { path: '/signup', name: 'Signup', component: Signup, }, { path: '/signout', name: 'Sigout', component: Signout, }, ] export default routes |