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:
Wygenerowanie 32 bajtów losowych znaków
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
}
}
}