Cookies en sessies
Finch biedt twee mechanismen om gegevens tussen HTTP-verzoeken te bewaren: cookies (client-side) en sessies (server-side). Het verschil begrijpen helpt je het juiste middel te kiezen:
- Cookies worden opgeslagen in de browser en meegestuurd met elk verzoek. Ze zijn geschikt voor lichte gebruikersvoorkeuren (thema, taal) die veilig client-side kunnen worden opgeslagen.
- Sessies worden op de server opgeslagen. Alleen een sessie-ID wordt naar de browser gestuurd. Ze zijn geschikt voor gevoelige gegevens, zoals de momenteel ingelogde gebruiker.
Beide zijn toegankelijk via het rq-object binnen elke controller of routehandler.
Cookies
Cookies zijn key-value-stringparen die in de browser worden opgeslagen. Finch leest ze uit inkomende Cookie-headers en schrijft ze via Set-Cookie-antwoordheaders.
Een cookie lezen
Gebruik rq.getCookie(key, def: defaultValue) om een cookie te lezen. De def-parameter geeft aan wat er wordt geretourneerd als de cookie niet bestaat.
safestaat bij zowelgetCookiealsaddCookiestandaard optrue. Tenzij je anders aangeeft, wordt elke cookie die Finch leest of schrijft transparant versleuteld/ontsleuteld. Om een echt platte-tekstwaarde op te slaan of te lezen (leesbaar in de devtools van de browser), moet je explicietsafe: falsedoorgeven:
// Versleuteld (standaard) — wordt automatisch ontsleuteld bij het terug lezen met getCookie
var token = rq.getCookie('auth_token', def: '');
// Onversleuteld — de waarde wordt exact zo opgeslagen en teruggegeven als opgegeven
var theme = rq.getCookie('theme', def: 'light', safe: false);
Een cookie schrijven
Gebruik rq.addCookie(key, value) om een cookie in te stellen. De cookie wordt aan het antwoord toegevoegd:
// Versleuteld (standaard)
rq.addCookie('auth_token', 'abc123');
// Onversleuteld
rq.addCookie('theme', 'dark', safe: false);
addCookie accepteert ook fijnmaziger opties voor de onderliggende Set-Cookie-header:
rq.addCookie(
'session_pref',
'compact',
safe: false,
duration: Duration(days: 30), // stelt Max-Age in
path: '/', // standaard is '/'
domain: '.example.com',
secure: true, // alleen verzenden over HTTPS
httpOnly: true, // niet leesbaar vanuit JavaScript
sameSite: SameSite.lax,
);
Een cookie verwijderen
Om een cookie te verwijderen, zet Finch deze opnieuw met een verlopen max-age:
rq.removeCookie('theme');
Volledig voorbeeld
class CookieController extends Controller {
Future<String> showCookie() async {
var value = rq.getCookie('test', def: 'not set', safe: false);
rq.addParam('cookieValue', value);
return rq.renderView(path: 'example/cookie');
}
Future<String> addCookie() async {
var key = rq.get<String>('key', def: '');
var value = rq.get<String>('value', def: '');
var safe = rq.get<bool>('safe', def: false);
if (key.isNotEmpty) {
rq.addCookie(key, value, safe: safe);
}
return rq.redirect('/example/cookie');
}
}
Sessies
Sessies worden beheerd door Dart's ingebouwde HttpSession. Elke bezoeker krijgt een unieke sessie-ID die wordt opgeslagen in een browsercookie, maar de daadwerkelijke gegevens bevinden zich op de server in het geheugen.
Belangrijk: De standaard Dart-
HttpSessionwordt in het geheugen bijgehouden. Sessiegegevens gaan verloren wanneer de server opnieuw opstart en worden niet gedeeld tussen meerdere serverinstanties achter een load balancer. Overweeg voor productiegebruik op schaal een persistente/gedeelde sessieopslag, of sla kritieke gegevens in plaats daarvan op in de database.
Een sessiewaarde lezen
Gebruik rq.getSession(key, def: defaultValue) om een waarde te lezen. Het retourneert def als de sleutel niet bestaat. Let op: het retourtype is Object, niet String — cast het als je een specifiek type nodig hebt:
var userEmail = rq.getSession('user', def: '') as String;
Een sessiewaarde schrijven
Gebruik rq.addSession(key, value) om een waarde op te slaan in de huidige sessie. De waarde kan elk JSON-vriendelijk type zijn (String, num, bool, Map, List), niet alleen strings:
rq.addSession('user', '[email protected]');
rq.addSession('cart', {'items': 3, 'total': 42.5});
Een sessiewaarde verwijderen
rq.session.remove('user');
Volledig voorbeeld
Een typische login/logout/dashboard-flow met sessies:
class SessionController extends Controller {
Future<String> login() async {
var email = rq.get<String>('email', def: '');
var password = rq.get<String>('password', def: '');
if (isValidUser(email, password)) {
// Sla het e-mailadres van de gebruiker op in de sessie na succesvolle authenticatie
rq.addSession('user', email);
return rq.redirect('/dashboard');
}
return rq.renderError(401);
}
Future<String> logout() async {
// Verwijder de gebruiker uit de sessie om uit te loggen
rq.session.remove('user');
return rq.redirect('/login');
}
Future<String> dashboard() async {
var email = rq.getSession('user', def: '') as String;
// Als er geen sessie is, is de gebruiker niet ingelogd — doorverwijzen naar login
if (email.isEmpty) return rq.redirect('/login');
rq.addParam('email', email);
return rq.renderView(path: 'pages/dashboard');
}
}
Voor een volledige authenticatieflow met permissies en routebeveiliging, zie Auth Controller — deze bouwt voort op dezelfde getSession/addSession-aanroepen die hier zijn getoond.
Hoe cookie-versleuteling werkt
De versleutelingssleutel is FinchConfigs.cookiePassword:
FinchConfigs configs = FinchConfigs(
cookiePassword: env.get('COOKIE_SECRET', 'change-this-in-production'),
);
// Schrijven — wordt versleuteld opgeslagen in de browser
rq.addCookie('prefs', '{"theme":"dark"}');
// Terug lezen — Finch ontsleutelt dit automatisch
var prefs = rq.getCookie('prefs', def: '{}');
Omdat de versleuteling is gekoppeld aan cookiePassword, maakt het wijzigen van die waarde elke cookie die al is opgeslagen in de browsers van bezoekers ongeldig — getCookie kan ze dan niet meer ontsleutelen en valt stilzwijgend terug op def.
Beveiliging: Gebruik een lange, willekeurige
cookiePassword. Sla deze op als omgevingsvariabele. Hardcode deze nooit en commit hem nooit naar versiebeheer.
Cookies lezen in sjablonen
Je kunt een cookiewaarde ook rechtstreeks binnen een Jinja-sjabloon lezen:
{{ $e.getCookie('theme', 'light') }}
Zie Template voor al het andere dat beschikbaar is op $e binnen een sjabloon.