Bagaimana Memvalidasi Sandi Lewat (Password) Lama User?


Laravel didistribusikan dengan fitur built-in untuk menyetel ulang sandi lewat. Bahkan, jika kita menggunakan Authentication dengan membuatnya melalui artisan, fitur tersebut sudah dapat berjalan tanpa mengubah apa-apa. Cukup ubah pengaturan SMTP email saja.

Tutorial kali ini menggunakan Laravel versi 5.3 untuk ujicoba. Penggunaan package, URI, dan komponen lainnya bisa berbeda jika diaplikasikan pada versi yang berbeda.

Umumnya, user lain, walaupun dengan role lebih tinggi (seperti administrator misalnya), tidak diperkenankan untuk mengganti langsung sandi lewat user lainnya. Karena hal tersebut berhubungan dengan privasi. Tidak peduli sandi lewatnya dibuat acak pada saat diisi, apalagi diisi sesuai dengan permintaan user tersebut.

Biasanya, dalam user management hanya disedikan sebuah tautan yang berisi aksi untuk menyetel ulang sandi lewat user terpilih. Aksi tersebut akan mengirim sebuah email yang berisi instruksi bagaimana menyetel ulang sandi lewat. Fitur ini sejatinya dapat menggunakan package Reset Password yang disediakan Laravel.

Namun, bagaimana jika user bersangkutan ingin mengubah sandi lewatnya sendiri?

Di dokumentasi Laravel, memang tidak dijelaskan secara gamblang bagaimana membuat fitur ubah sandi lewat. Namun, berbekal pengetahuan yang ada pada package Hashing dan Validation, fitur tersebut dapat kita buat sendiri. Cukup dengan tiga langkah mudah.

Alur kerja:

  1. Status user sudah harus login ke dalam sistem.
  2. User memasukkan informasi sandi lewat lama, sandi lewat baru, dan konfirmasi sandi lewat.
  3. Form dikirim untuk divalidasi dan diproses.
  4. Data valid, kemudian sandi lewat baru disimpan.

Membuat dan Menggunakan Authentication

Pastikan Laravel sudah diinstal di mesin lokal dan pengaturan sudah disesuaikan.

Masuk ke direktori utama Laravel, dan jalankan perintah di bawah:

$ php artisan make:auth

Dari perintah di atas, terdapat berkas baru yang disalin ke direktori resource. Berkas tersebut berisi layout utama dan beberapa form untuk login, register, dsb.

../views
├── auth
│   ├── login.blade.php
│   ├── passwords
│   │   ├── email.blade.php
│   │   └── reset.blade.php
│   └── register.blade.php
├── errors
│   └── 503.blade.php
├── home.blade.php
├── layouts
│   └── app.blade.php
├── vendor
└── welcome.blade.php

Sebelum dapat dijalankan melalui peramban (browser), jalankan migrasi, kemudian jalankan built-in web server. Perintahnya secara berturut-turut sebagai berikut.

$ php artisan migrate
$ php artisan serve

Akses URL http://localhost:8000 pada peramban. Buat beberapa user baru dengan mendaftar melalui URI /register.

Membuat Form Ubah Sandi Lewat

Dalam distribusinya, Laravel menyediakan default template yang berbasis Bootstrap. Template ini akan disalin dari direktori vendor ke direktori resource/views apabila berhasil membuat Authentication seperti contoh di atas.

Nah, template ini akan kita gunakan sebagai basis untuk form ubah sandi lewat nantinya.

views
├── auth
│   ├── login.blade.php
│   ├── passwords
│   │   ├── email.blade.php
│   │   └── reset.blade.php
│   └── register.blade.php
├── errors
│   └── 503.blade.php
├── home.blade.php
├── layouts
│   └── app.blade.php
├── password
│   └── change.blade.php
├── vendor
└── welcome.blade.php

Buat berkas baru pada direktori views/password/ dengan nama change.blade.php. Modifikasi berkas tersebut sehingga isinya kurang lebih seperti ini.

@extends('layouts.app')
 
@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Change Password</div>
                <div class="panel-body">
                    @if (session()->has('success'))
                        <div class="alert alert-success">{{ session('success') }}</div>
                    @endif
 
                    <form class="form-horizontal" role="form" method="POST" action="{{ route('password.update') }}">
 
                        {{ csrf_field() }}
                        {{ method_field('put') }}
 
                        <div class="form-group{{ $errors->has('current_password') ? ' has-error' : '' }}">
                            <label for="current_password" class="col-md-4 control-label">Current Password</label>
 
                            <div class="col-md-6">
                                <input id="current_password" type="password" class="form-control" name="current_password" autofocus>
                                <span class="help-block">{{ $errors->first('current_password') }}</span>
                            </div>
                        </div>
 
                        <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
                            <label for="password" class="col-md-4 control-label">New Password</label>
 
                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control" name="password">
                                <span class="help-block">{{ $errors->first('password') }}</span>
                            </div>
                        </div>
 
                        <div class="form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }}">
                            <label for="password_confirmation" class="col-md-4 control-label">New Password Confirmation</label>
 
                            <div class="col-md-6">
                                <input id="password_confirmation" type="password" class="form-control" name="password_confirmation">
                                <span class="help-block">{{ $errors->first('password_confirmation') }}</span>
                            </div>
                        </div>
 
                        <div class="form-group">
                            <div class="col-md-8 col-md-offset-4">
                                <button type="submit" class="btn btn-primary">
                                    Change Password
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Hasil akhir kode tersebut jika dilihat melalui peramban kurang lebih seperti berikut.

Membuat Custom Validation dan Controller

Ada dua hal yang dilakukan pada bagian ini, yaitu mendefinisikan route, dan membuat controller baru dengan nama PasswordController.php.

Route::group(['middleware' => 'auth'], function () {
    Route::get('password', 'PasswordController@change')->name('password.change');
    Route::put('password', 'PasswordController@update')->name('password.update');
});

Perhatikan bahwa saya mendefinisikan dua URI yang sama., yaitu password. Route pertama menggunakan PasswordController dengan method change() yang berfungsi untuk menampilkan form ubah sandi lewat. Sedangkan route kedua menggunakan controller yang sama, hanya saja HTTP Verb dan method-nya berbeda. Route yang keda ini berfungsi untuk memvalidasi data dan menyimpan sandi lewat baru.

Tak lupa juga saya menambahkan middleware auth pada kedua route tersebut. Hal ini untuk memastikan bahwa user yang sudah login lah yang dapat mengganti sandi lewatnya.

Sedangkan untuk isian controller, dapat dilihat pada potongan kode berikut.

<?php
 
namespace App\Http\Controllers;
 
use App\User;
use Auth;
use Hash;
use Validator;
 
/**
 * @author Yugo <dedy.yugo.purwanto@gmail.com>
 * @copyright Laravel.web.id - 2016
 */
class PasswordController extends Controller
{
    /**
     * @return mixed
     */
    public function change()
    {
        return view('password.change');
    }
 
    /**
     * @return mixed Redirect
     */
    public function update()
    {
        // custom validator
        Validator::extend('password', function ($attribute, $value, $parameters, $validator) {
            return Hash::check($value, \Auth::user()->password);
        });
 
        // message for custom validation
        $messages = [
            'password' => 'Invalid current password.',
        ];
 
        // validate form
        $validator = Validator::make(request()->all(), [
            'current_password'      => 'required|password',
            'password'              => 'required|min:6|confirmed',
            'password_confirmation' => 'required',
 
        ], $messages);
 
        // if validation fails
        if ($validator->fails()) {
            return redirect()
                ->back()
                ->withErrors($validator->errors());
        }
 
        // update password
        $user = User::find(Auth::id());
 
        $user->password = bcrypt(request('password'));
        $user->save();
 
        return redirect()
            ->route('password.change')
            ->withSuccess('Password has been updated.');
    }
 
}

Dimulai dari baris ke 30, saya meng-extend validasi dengan nama password. Isinya melakukan pengecekan persamaan sandi lewat yang dimasukkan oleh user dengan sandi lewat lama yang disimpan. Proses pengecekan ini menggunakan package Hashing bawaan Laravel.

Berikutnya, dimulai dari baris ke 40 didefinisikan validasi untuk masukan dari form. Langkah selanjutnya, cuup mudah dipahami menurut saya, ialah melakukan validasi dan mengambalikan ke halaman yang sama apabila validasi gagal dan tidak lupa untuk menampilkan pesan kesahalan.

Langkah terakhir, apabila data valid, sandi lewat baru disimpan ke basisdata menggunakan fungsi bcrypt().

Selain menggunakan facade Validator seperti contoh di atas, kita juga bisa memvalidasi masukkan menggunakan form request.

Konklusi

Fitur ubah sandi lewat merupakan salah satu yang harus ada pada aplikasi web. Apalagi jika aplikasi yang kita bangun menerapkan fitur seamless login, misal login menggunakan akun Facebook atau Google.

Untuk contoh lengkap kode di atas, dapat meng-clone repositori Github yang beralamat di arvernester/tutorial.

Jangan lupa untuk membaca panduan instalasinya. 😉

 

Tak Berkategori

Yugo Purwanto

Pemrogram PHP dan JavaScript yang sedang sibuk mengembangkan aplikasi Glosarium Bahasa Indonesia.

Tinggalkan Balasan