Przejdź do treści

Redis i sesje#

Redis może pełnić rolę dostawcy przechowywania danych do buforowania danych sesji, takich jak dane uwierzytelniające użytkownika.

Jeśli niestandardowy RedisSessionsDelegate nie zostanie dostarczony, zostanie użyty domyślny.

Domyślne zachowanie#

Tworzenie SessionID#

Jeśli nie zaimplementujesz metody makeNewID() we własnym RedisSessionsDelegate, wszystkie wartości SessionID będą tworzone w następujący sposób:

  1. Wygenerowanie 32 bajtów losowych znaków

  2. Zakodowanie wartości w base64

Na przykład: Hbxozx8rTj+XXGWAzOhh1npZFXaGLpTWpWCaXuo44xQ=

Przechowywanie SessionData#

Domyślna implementacja RedisSessionsDelegate przechowuje SessionData jako prosty ciąg znaków JSON przy użyciu Codable.

Jeśli nie zaimplementujesz metody makeRedisKey(for:) we własnym RedisSessionsDelegate, SessionData będzie przechowywane w Redis pod kluczem, który poprzedza SessionID prefiksem vrs- (Vapor Redis Sessions)

Na przykład: vrs-Hbxozx8rTj+XXGWAzOhh1npZFXaGLpTWpWCaXuo44xQ=

Rejestrowanie niestandardowego delegata#

Aby dostosować sposób odczytu i zapisu danych w Redis, zarejestruj własny obiekt RedisSessionsDelegate w następujący sposób:

import Redis

struct CustomRedisSessionsDelegate: RedisSessionsDelegate {
    // implementation
}

app.sessions.use(.redis(delegate: CustomRedisSessionsDelegate()))

RedisSessionsDelegate#

Dokumentacja API: RedisSessionsDelegate

Obiekt zgodny z tym protokołem może być użyty do zmiany sposobu przechowywania SessionData w Redis.

Typ zgodny z protokołem musi implementować tylko dwie metody: redis(_:store:with:) oraz redis(_:fetchDataFor:).

Obie są wymagane, ponieważ sposób, w jaki dostosowujesz zapis danych sesji do Redis, jest nierozerwalnie związany ze sposobem ich odczytu z Redis.

Przykład RedisSessionsDelegate z użyciem Hash#

Na przykład, jeśli chcesz przechowywać dane sesji jako Hash w Redis, możesz zaimplementować coś w następujący sposób:

func redis<Client: RedisClient>(
    _ client: Client,
    store data: SessionData,
    with key: RedisKey
) -> EventLoopFuture<Void> {
    // stores each data field as a separate hash field
    return client.hmset(data.snapshot, in: key)
}
func redis<Client: RedisClient>(
    _ client: Client,
    fetchDataFor key: RedisKey
) -> EventLoopFuture<SessionData?> {
    return client
        .hgetall(from: key)
        .map { hash in
            // hash is [String: RESPValue] so we need to try and unwrap the
            // value as a string and store each value in the data container
            return hash.reduce(into: SessionData()) { result, next in
                guard let value = next.value.string else { return }
                result[next.key] = value
            }
        }
}
Edytuj tę stronę