Laravel, Javascript & Cookies

L

Weer zo’n gevalletje dat alle informatie verspeid over internet staan: Laravel, Javascript en cookies. Het was dus even zoeken voordat ik het werkend had, maar zoals altijd: als je het eenmaal weet, dan is het eigenlijk best eenvoudig. Hierbij mijn bevindingen in het kort.

Als de cookie leesbaar moet zijn voor de Javascript in de browser, dan moet er rekening mee worden gehouden dat de cookie niet versleuteld moet worden. Laravel doet dat standaard, maar daar is gelukkig ook eenvoudig een uitzonder op te maken via de middleware \App\Http\Middleware\EncryptCookies. In de $except array kan de naam van de cookie opgenomen worden die niet ge-encrypt hoeft te worden. In dit geval ging het om een cookie met de naam tax:

<?php

namespace App\Http\Middleware;

use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;

class EncryptCookies extends Middleware
{
    /**
     * The names of the cookies that should not be encrypted.
     *
     * @var array
     */
    protected $except = [
        'tax'
    ];
}

In een ander stukje middleware lees ik de cookie uit en maak er een globale view variabele van. De reden hiervoor is dat het tonen van prijzen met / zonder BTW door vele views heen gebruikt wordt. Uiteraard moet je in onderstaande code het domein (test.local) vervangen voor het domein waarop het geheel echt draait. Gebruik geen localhost als het lokaal draait, want dat geeft problemen. Zet desnoods iets in je hosts file dat naar 127.0.0.1 wijst. Bijvoorbeeld test.local.

<?php

namespace App\Http\Middleware;

use App\Tools\Tax;
use Closure;
use Illuminate\Http\Request;

class HandleCookie
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        $tax = Tax::DEFAULT;

        if( $request->hasCookie('tax')) {
            $tax = $request->cookie( 'tax', Tax::DEFAULT );
        }
        \View::share( 'showTax', $tax );

        $response = $next($request);

        return $response->withCookie( \Cookie::forever('tax', $tax, "/", ".test.local", false, false, false, "lax" ) );
    }
}

Belangrijk in de bovenstaande code is de withCookie aanroep: de httpOnly parameter (2e false), moet niet op true gezet worden. Dan is de cookie niet aan te passen aan de browser zijde door de Javascript. Ook de sameSite parameter (“lax”) moet gezet worden om problemen te voorkomen.

In de browser was er een schakelaar om te wisselen tussen in- en exclusief BTW prijzen. Deze toggle maakte een aanroep naar de onderstaande Javascript functie. Let op dat hier het zelfde domain en path gebruikt worden, aangezien er anders dubbele cookies ontstaan. In dit geval is er gekozen om het domein op .test.local te zetten, zodat de cookie beschikbaar is op test.local, maar ook op alle subdomeinen onder test.local.

function set(cookieName, cookieValue, expirationDays) {
    expirationDays = expirationDays || 3;
    const d = new Date();
    d.setTime(d.getTime() + (expirationDays * 24 * 60 * 60 * 1000));

    // Infinite January 19th, 2038
    if (expirationDays === -1) {
        d.setTime(2147483646 * 1000);
    }

    let p = window.location.hostname.split(".").reverse();
    const domain = "domain=." + p[1] + "." + p[0];
    const expires = `expires=${d.toUTCString()}`;

    document.cookie= `${cookieName}=${encodeURIComponent(cookieValue)};${expires};${domain};path=/;SameSite=lax`;
}

About the author

Add Comment

By Marc