Autentikimi

Në Laravel, sistemi i autentikimit vie i gatshëm. Mund të krijohet me komandat:

php artisan make:auth

dhe

php artisan migrate

Pas kësaj, kemi në dispozicion rutat:

  • /register për regjistrim,
  • /login për autentikim,
  • /logout për dalje,
  • /password/reset për ndryshimin e fjalëkalimit

Me ketë rast krijohen edhe kontrollerët përkatës në folderin App\Http\Controllers\Auth:

  • LoginController, që menaxhon autentikimin,
  • RegisterController, që menaxhon regjistrimet e reja,
  • ResetPasswordController, që menaxhon ndryshimin e fjalëkalimit,
  • ForgotPasswordController, që menaxhon dërgimin e emailit me link për konfirmimin e kërkesës për ndryshimin e fjalëkalimit

Këta kontrollerë përdorin traits përkatës:

- Illuminate\Foundation\Auth\AuthenticatesUsers

  • Illuminate\Foundation\Auth\RegistersUsers
  • Illuminate\Foundation\Auth\ResetsPasswords
  • Illuminate\Foundation\Auth\SendsPasswordResetEmails

Brenda këtyre traits, bëhet thirrja e views dhe validimi i inputit.

app/Http/Middleware krijohet fajlli RedirectIfAuthenticated.php, i cili është middleware që redirekton përdoruesin e autentikuar në rutën /home.

Në folderin resources/views, krijohet folderi auth, brenda të cilit janë Blade fajllat përkatës:

  • login.blade.php
  • register.blade.php
  • passwords/reset.blade.php
  • passwords/email.blade.php

The make:auth command will also create a resources/views/layouts directory containing a base layout for your application. All of these views use the Bootstrap CSS framework, but you are free to customize them however you wish.

Komanda make:auth po ashtu krijon folderin resources/views/layouts brenda të cilit gjendet fajlli app.blade.php që përmban shabllonin bazik të aplikacionit.

Konfigurimi i autentikimit bëhet në fajllin app/config/auth.php. Konfigurimi standard është si vijon:

return [
    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
    ],

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],
];

Mekanizmi i autentikimit në Laravel shfrytëzon "guards" dhe "providers".

"Guards" përcaktojnë mënyrën e autentikimit të përdoruesve gjatë çdo kërkese (request). Drajveri standards është sessions, me çka mundësohet ruajtja e gjendjes me anë të të dhënave të sesionit dhe cookie-ve.

Provajderët përcaktojnë mënyrën e leximit të përdoruesve nga databaza. Kjo mund të bëhet me Eloquent apo me database query builder, duke zgjedhur në providers.users.driver vlerat eloquent apo database. Sipas nevojës, mund të krijohen edhe provajderë të tjerë.

Gjatë instalimit të Laravel, krijohet një fajll User.php në folderin app, dhe pikërisht ky model përdoret si drajver i autentikimit. Nëse në aplikacionin tonë nuk e përdorim Eloquentin, si drajver të autentikimit zgjedhim database, i cili përdor query builder në vend të Eloquentit.

database/migrations gjendet fajlli 2014_10_12_000000_create_users_table.php , ku krijohet skema për tabelën users.

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

Fusha password duhet ta ketë gjatësinë së paku 60 karaktere për ruajtjen e hash-it të fjalëkalimit.

Në të njëjtën tabelë duhet të ekzistojë edhe fusha remember_token me gjatësi së paku prej 100 karakteresh. Kjo fushë krijohet me metodën rememberToken(). Në këtë fushë ruhet tokeni kur përdoruesi klikon në "Remember me".

Path Customization

Siç u përmend edhe më parë, përdoruesi i autentikuar redirektohet në rutën /home. Kjo rutë mund të ndryshohet duke e definuar vetinë redirectToLoginController, RegisterController, dhe ResetPasswordController:

protected $redirectTo = '/';

Poashtu duhet të modifikohet metoda handle e RedirectIfAuthenticated middleware për ta përdorur rutën e re gjatë redirektimit.

Nëse redirektimi kërkon logjikë më komplekse për të ardhur deri te ruta, duhet të definohet metoda redirectTo në vend të vetisë redirectTo:

<?php
protected function redirectTo()
{
    return '/path';
}

Metoda redirectTo() ka precedencë më të lartë se vetia redirectTo.

Username Customization

Si emër përdorues gjatë autentikimit, Laravel kërkon nëpër fushën email të modelit User. Nëse duam ta ndryshojmë këtë, dhe në vend të emailit për shembull ta përdorim fushën username, definojmë metodën username() në kontrollerin LoginController, e cila kthen si rezultat emrin e fushës së tabelës kur ruhet emri përdorues (user name):

public function username()
{
    return 'username';
}

Natyrisht, një fushë e tillë duhet të ekzistojë në tabelën users dhe duhet të jetë e plotësuar me një vlerë unike.

Guard Customization

Mund të bëhet përshtatja e "guard" që përdoret për autentikimin dhe regjistrimin e përdoruesve. Për këtë duhet të definohet metoda guard() në kontrollerët LoginController, RegisterController, dheResetPasswordController. Metoda duhet të kthejë instancë të "guard".

use Illuminate\Support\Facades\Auth;

protected function guard()
{
    return Auth::guard('guard-name');
}

Validimi

Për modifikimin e fushave të formularit që janë të nevojshme gjatë regjistrimit të një anëtari të ri, apo për përshtatjen e mënyrës së ruajtjes së anëtarëve të rinj në databazë, bëhet modifikimin i klasës RegisterController. Kjo klasë merret me validimin dhe krijimin i anëtarëve të rinj.

Metoda validator() e RegisterController përmban rregullat e validimit për anëtarët e rinj, të cilat rregulla ne mund t'i ndryshojmë sipas dëshirës.

Metoda create() e RegisterController është përgjegjëse për krijimin e rradhëve të reja të App\User në tabelën gjegjëse në databazë. Këtë metodë mund ta modifikojmë sipas nevojës.

Leximi i përdoruesit të autentikuar

Përdoruesi i autentikuar lexohet nëpërmes fasadës Auth.

use Illuminate\Support\Facades\Auth;

// Get the currently authenticated user...
$user = Auth::user();

// Get the currently authenticated user's ID...
$id = Auth::id();

Një mënyrë tjetër e leximit të përdoruesit është nëpërmes instancës së Illuminate\Http\Request. Klasat e shënuara si parametra të metodës (type-hinted classes) automatikisht injektohen në metodën e kontrollerit.

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ProfileController extends Controller
{
    public function update(Request $request)
    {
        // $request->user() kthen një instancë të përdoruesit të autentikuar
    }
}

Determinimi nëse përdoruesi aktual është i autentikuar

Për të determinuar nëse përdoruesi tashmë është autentikuar, mund të përdoret metoda check() në fasadën Auth, që si rezultat kthen true nëse përdoruesi është autentikuar.

use Illuminate\Support\Facades\Auth;

if (Auth::check()) {
    // The user is logged in...
}

Mbrojtja e rutave

Route middleware mund të përdoret që të lejojë qasjen në një rutë vetëm të përdoruesve të autentikuar.

Laravel vie me një middleware auth që është i definuar në Illuminate\Auth\Middleware\Authenticate. Duke qenë se ky middleware vie i regjistruar në HTTP kernel, mjafton që të atashohet në një definicion të rutës.

Route::get('profile', function () {
    // Vetëm përdoruesit e autentikuar mund të futen në rutën profile
})->middleware('auth');

Middleware auth mund të thirret edhe nga konstruktori i kontrollerit, me çka mundësohet që vetëm anëtarët e autentikuar të kenë mundësi qasjeje në atë kontroller.

public function __construct()
{
    $this->middleware('auth');
}

Redirektimi i përdoruesve të paautentikuar

Kur middleware auth detekton një përdorues të paautentikuar, do ta bëjë redirektimin në rutën login, ose në rastin e kërkesës me AJAX, kthen JSON 401 response.

Kjo sjellje mund të modifikohet duke e definuar në metodë unauthenticated në fajllin app/Exceptions/Handler.php.

use Illuminate\Auth\AuthenticationException;

protected function unauthenticated($request, AuthenticationException $exception)
{
    return $request->expectsJson()
                ? response()->json(['message' => $exception->getMessage()], 401)
                : redirect()->guest(route('login'));
}

Specifikimi i një guard

Kur atashohet një auth middleware në rutë, mund të specifikojmë edhe cili guard duhet të përdoret për autentikimin e përdoruesit. Guard-i duhet të jetë një nga ata që janë të definuar në vargun guards të fajllit të konfigurimit auth.php.

public function __construct()
{
    $this->middleware('auth:api');
}

Login Throttling

Nëse jemi duke e përdorur klasën LoginController, trait Illuminate\Foundation\Auth\ThrottlesLogins përfshihet në kontroller. Përdoruesi nuk do të mundet të kyqet në sistem 1 minutë nëse japin kredenciale të gabuara disa herë radhazi.

Autentikimi manual i përdoruesve

Nëse nuk dëshirojmë t'i përdorim kontrollerët e gatshëm që vijnë me Laravel, mund t'i përdorim drejtpërsëdrejti klasat e Laravel për autentikim.

Serviseve të autentikimit mund t'i qasemi nëpërmes fasadës 'Illuminate\Support\Facades\Auth', ndërsa autentikimin e bëjmë me metodën 'attempt()', së cilës ia përcjellim anëtarët email dhe password të objektit Request $request.

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    public function authenticate(Request $request)
    {
        $credentials = $request->only('email', 'password');

        if (Auth::attempt($credentials)) {
            // Authentication passed...
            return redirect()->intended('dashboard');
        }
    }
}

Metoda attempt() pranon një varg të çifteve çelës/vlerë si argument të parë të sajën. Vlerat në atë varg do të përdoren për gjetjen e përdoruesit në tabelën e databazës. Në këtë shembull, përdoruesi do të kërkohet në bazë të vlerës në fushën email. Nëse gjendet përdoruesi, hashi i fjalëkalimit i ruajtur në databazë do të krahasohet me vlerën e password që ruhet në $credentials e që duhet të jetë fjalëkalimi në formën tekstuale dhe jo hash.

Metoda attempt kthen true nëse autentikimi ka qenë i suksesshëm, përndryshe kthen false.

Metoda intended()redirect()->intended('dashboard') bën redirektimin e përdoruesit në URL-në e synuar për përdoruesin e autentikuar.

Specifikimi i kritereve shtesë

Përveç emailit dhe fjalëkalimit, mund të shtojmë edhe kritere të tjera shtesë.

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
    // The user is active, not suspended, and exists.
}

Në këtë shembull, përveç emailit dhe fjalëkalimit, kërkohet që fusha active në rreshtin e tabelës së përdoruesve në databazë ta ketë vlerën 1.

Qasja e instancave të rojeve specifike

Me përdorimin e metodës guard() të fasadës Auth, mund të specifikojmë se cilën instancë të rojes dëshirojmë ta përdorim. Kjo mundëson menaxhimin e autentikimit për pjesë të veçanta të aplikacionit duke përdorur modele dhe tabela të veçanta për përdoruesit.

Emri i rojes që i përcillet metodës guard() duhet t'i korrespondojë njërës prej rojeve të konfiguruara në fajllin konfigurues auth.php.

if (Auth::guard('admin')->attempt($credentials)) {
    //
}

Në këtë shembull, tentohet autentikimi i përdoruesit, duke e përdorur rojen admin, të cilit i korrespondon një model dhe/ose tabelë e veçantë, ashtu siç është definuar në auth.php.

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'admin' => [
        'driver' => 'session',
        'provider' => 'admin',
    ],
    'api' => [
        'driver' => 'token',
        'provider' => 'users',
    ],

Në shembullin konkret, përdoruesit që i takojnë rojes admin i kanë të dhënat (emaili, fjalëkalimi, etj.) në tabelë të veçantë admin në databazë.

Çlajmërimi

Për çlajmërimin e përdoruesit nga aplikacionit, përdoret metoda logout() në fasadën Auth.

Auth::logout();

Mbajtja në mend e përdoruesve

Për t'ia ofruar funksionalitetin "remember me" aplikacionit, si argument të dytë e japim vlerën true. Me këtë do të mundësohet që përdoruesi të mbetet i autentikuar deri në momentin kur çlajmërohet manualisht nga aplikacioni.

Për ta ruajtur tokenin në tabelën e përdoruesve, duhet të krijohet fusha remember_token të tipit VARCHAR me gjatësi prej 100 karakteresh. Për krijimin e kësaj fushe, në Schema përdoret: $table->rememberToken();.

if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
    // The user is being remembered...
}

Nëse përdoret LoginController që vie me Laravel, logjika për "remember me" vie e implementuar.

Metoda viaRemember() e fasadës Auth tregon nëse përdoruesi është identifikuar me "remember me" cookie.

if (Auth::viaRemember()) {
    //
}

Metodat tjera të autentikimit

Autentikimi i një instance të përdoruesit

Nëse duhet që një përdorues të autentikohet në aplikacion, kjo realizohet me metodën login() të cilit i bartet instanca e përdoruesit. Objekti i bartur duhet të jetë implementim i kontratës Illuminate\Contracts\Auth\Authenticatable contract. Modeli App\User e ka të implementuar këtë interfejs.

Auth::login($user);

// Login and "remember" the given user...
Auth::login($user, true);

Nëse duhet të ceket edhe roja (guard), duhet të ceket instanca e rojes që do të përdoret.

Auth::guard('admin')->login($user);

Autentikimi i përdoruesit me ID

Për autentikimin e një përdoruesi në bazë të ID-së së tij, duhet të përdoret metoda loginUsingId.

Auth::loginUsingId(1);

// Login and "remember" the given user...
Auth::loginUsingId(1, true);

Autentikimi i përdoruesit një herë

Metoda once() mundëson autentikimin e përdoruesit për vetëm një kërkesë (request). Me këtë rast nuk krijohet sesion apo cookie.

if (Auth::once($credentials)) {
    //
}

HTTP Basic Authentication

HTTP Autentikimi Bazik (HTTP Basic Authentication) mundëson një mënyrë të thjeshtë për autentikim, pa pasur nevojë për një faqe me formular për shënimin e kredencialeve. Për ta realizuar autentikimin bazik, rutës së dëshiruar ia shtojmë ->middleware('auth.basic').

Route::get('profile', function () {
    // Only authenticated users may enter...
})->middleware('auth.basic');

Me rastin e thirrjes së rutës së cekur, do të paraqitet një "dialog box" ku duhet të shënohen emaili dhe fjalëkalimi.

Nëse jeni duke përdorur PHP FastCGI, HTTP Autentikimi Bazik mund të mos funksionojë, prandaj në .htaccess duhet të shtohen rreshtat vijues:

RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Stateless HTTP Basic Authentication

HTTP Autentikimi Bazik mund të përdoret edhe pa e krijuar një cookie identifikues në sesion dhe kjo metodë është e përshtatshme për autentikim nëpërmes API. Për këtë definohet një middleware që e thirr metodën onceBasic(). Nëse metoda onceBasic() nuk kthen përgjigje (response), kërkesa (request) mund të vijojë më tej në aplikacion.

<?php
namespace App\Http\Middleware;
use Illuminate\Support\Facades\Auth;
class AuthenticateOnceWithBasicAuth
{
    public function handle($request, $next)
    {
        return Auth::onceBasic() ?: $next($request);
    }
}
Route::get('api/user', function () {
    // Only authenticated users may enter...
})->middleware('auth.basic.once');

Çlajmërimi

Për çlajmërim manual të përdoruesit nga aplikacioni, përdoret metoda logout() e fasadës Auth, me çka fshihen të gjitha të dhënat e sesionit.

use Illuminate\Support\Facades\Auth;

Auth::logout();

Invalidating Sessions On Other Devices

Laravel also provides a mechanism for invalidating and "logging out" a user's sessions that are active on other devices without invalidating the session on their current device. Before getting started, you should make sure that the Illuminate\Session\Middleware\AuthenticateSession middleware is present and un-commented in your app/Http/Kernel.php class' web middleware group:

'web' => [
    // ...
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    // ...
],

Then, you may use the logoutOtherDevices method on the Auth facade. This method requires the user to provide their current password, which your application should accept through an input form:

use Illuminate\Support\Facades\Auth;

Auth::logoutOtherDevices($password);

When the

logoutOtherDevices

method is invoked, the user's other sessions will be invalidated entirely, meaning they will be "logged out" of all guards they were previously authenticated by.

Adding Custom Guards

You may define your own authentication guards using the extend method on the Auth facade. You should place this call to extend within a service provider. Since Laravel already ships with an AuthServiceProvider, we can place the code in that provider:

namespace App\Providers;

use App\Services\Auth\JwtGuard;
use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * Register any application authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Auth::extend('jwt', function ($app, $name, array $config) {
            // Return an instance of Illuminate\Contracts\Auth\Guard...

            return new JwtGuard(Auth::createUserProvider($config['provider']));
        });
    }
}

As you can see in the example above, the callback passed to the extend method should return an implementation of Illuminate\Contracts\Auth\Guard. This interface contains a few methods you will need to implement to define a custom guard. Once your custom guard has been defined, you may use this guard in the guards configuration of your auth.phpconfiguration file:

'guards' => [
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

Events

Laravel raises a variety of events during the authentication process. You may attach listeners to these events in your EventServiceProvider:

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'Illuminate\Auth\Events\Registered' => [
        'App\Listeners\LogRegisteredUser',
    ],

    'Illuminate\Auth\Events\Attempting' => [
        'App\Listeners\LogAuthenticationAttempt',
    ],

    'Illuminate\Auth\Events\Authenticated' => [
        'App\Listeners\LogAuthenticated',
    ],

    'Illuminate\Auth\Events\Login' => [
        'App\Listeners\LogSuccessfulLogin',
    ],

    'Illuminate\Auth\Events\Failed' => [
        'App\Listeners\LogFailedLogin',
    ],

    'Illuminate\Auth\Events\Logout' => [
        'App\Listeners\LogSuccessfulLogout',
    ],

    'Illuminate\Auth\Events\Lockout' => [
        'App\Listeners\LogLockout',
    ],

    'Illuminate\Auth\Events\PasswordReset' => [
        'App\Listeners\LogPasswordReset',
    ],
];