Identyfikacja odwiedzających i przekazywanie kontekstu
Jak zgłaszać zalogowanych użytkowników przez ReactiveChat('identify'), podpisywać userHash przez HMAC-SHA256 na twoim serwerze, rotować sekret i przekazywać asystentowi uporządkowany kontekst strony, np. produkt lub koszyk.
Jeśli twoja strona wie, kto jest właśnie na niej, powiedz to czatowi. Wtedy twój zespół widzi w panelu nazwisko zamiast „Odwiedzający 4f2a”, a funkcje takie jak dane klientów i portal klienta w ogóle stają się możliwe.
Zasada: przeglądarka niczego nie dowodzi. To, co strona twierdzi przez identify, każdy odwiedzający może sfałszować w konsoli. Za potwierdzonego uchodzi użytkownik tylko z podpisem, który twój serwer obliczył sekretem, który nigdy nie trafia do przeglądarki.
Wywołanie w przeglądarce
ReactiveChat('identify', {
userId: '4711',
email: 'kim@example.com',
name: 'Kim Berger',
userHash: '9c1f…',
exp: 1792503600
});
- userId (String, zalecany) – twój własny, trwały identyfikator użytkownika. Nie adres e-mail, nie numer kolejny, który może się zmienić.
- email (String, opcjonalny) – wyświetlany w panelu. Jest potwierdzony tylko wtedy, gdy został podpisany razem z resztą (niżej).
- name (String, opcjonalny) – nazwa wyświetlana w panelu.
- userHash (String, obowiązkowy do potwierdzenia) – 64 znaki hex, obliczone na twoim serwerze.
- exp (liczba całkowita, zalecany) – czas wygaśnięcia hasha w sekundach Unix, najwyżej 24 godziny w przyszłości.
Inne pola są odrzucane. identify może stać przed załadowaniem widżetu; trafia do kolejki i nie wyzwala wcześniejszego ładowania. Wartości są wysyłane przy nawiązaniu połączenia, a jeśli widżet jest już połączony – od razu.
Sekret
W koncie, w sekcji Projekt → Weryfikacja tożsamości, tworzysz sekret projektu (uprawnienie: edycja projektu). Składa się z 64 znaków hex i jest pokazywany w całości dokładnie raz, potem już tylko zamaskowany. Umieść go w środowisku swojego serwera – nigdy w skrypcie w przeglądarce, w aplikacji ani w repozytorium.
Ważne przy obliczaniu: kluczem HMAC jest sam 64-znakowy ciąg, dokładnie taki, jak jest wyświetlany – a nie zdekodowane z niego bajty.
Obliczanie podpisu
userHash = hex( HMAC_SHA256( geheimnis, userId + "." + exp ) )
Hex małymi literami, 64 znaki. Z potwierdzonym adresem e-mail:
userHash = hex( HMAC_SHA256( geheimnis, userId + "." + exp + "." + email ) )
Tylko w drugiej formie adres e-mail uchodzi za potwierdzony. Wymaga ona exp.
PHP:
<?php
$geheim = getenv('RC_IDENT_SECRET'); // 64 znaki hex z konta
$userId = (string) $kunde->id;
$exp = time() + 3600; // najwyżej 24 h
$userHash = hash_hmac('sha256', $userId . '.' . $exp, $geheim);
?>
<script nonce="<?= $cspNonce ?>">
ReactiveChat('identify', {
userId: <?= json_encode($userId) ?>,
userHash: <?= json_encode($userHash) ?>,
exp: <?= (int) $exp ?>
});
</script>
Node.js:
const crypto = require('crypto');
function rcIdentitaet(kunde) {
const userId = String(kunde.id);
const exp = Math.floor(Date.now() / 1000) + 3600;
const userHash = crypto.createHmac('sha256', process.env.RC_IDENT_SECRET)
.update(userId + '.' + exp)
.digest('hex');
return { userId, userHash, exp };
}
Python:
import hmac, hashlib, os, time
def rc_identitaet(kunde_id: str) -> dict:
exp = int(time.time()) + 3600
msg = f"{kunde_id}.{exp}".encode()
key = os.environ["RC_IDENT_SECRET"].encode() # ciąg hex jako tekst
return {"userId": kunde_id, "exp": exp,
"userHash": hmac.new(key, msg, hashlib.sha256).hexdigest()}
Z adresem e-mail (PHP):
$userHash = hash_hmac('sha256', $userId . '.' . $exp . '.' . $email, $geheim);
Adres musi być podpisany dokładnie tak, jak przekazujesz go do identify.
Bez skryptu inline (ścisła CSP)
Jeśli twoja Content Security Policy nie dopuszcza skryptów inline, wypisz wartości jako dane i wywołaj identify z osobnego pliku skryptu:
<meta name="rc-ident" content='{"userId":"4711","userHash":"9c1f…","exp":1792503600}'>
// /js/chat-ident.js
var m = document.querySelector('meta[name="rc-ident"]');
if (m) { ReactiveChat('identify', JSON.parse(m.content)); }
W aplikacjach jednostronicowych pobierasz te trzy wartości po zalogowaniu przez fetch ze swojego serwera.
Co sprawdza serwer
expjest liczbą całkowitą (sekundy Unix), leży w przyszłości i najwyżej 24 godziny (plus 5 minut tolerancji) naprzód.- Hash pasuje do
userId + "." + exp(albo wersji z e-mailem). Wielkie litery w hashu są tolerowane. - Porównanie odbywa się w stałym czasie.
Potwierdzony i świeży jest użytkownik z prawidłowym hashem i exp. Tylko wtedy dostaje dane klientów i portal klienta.
Starsza forma bez exp: userHash = HMAC_SHA256(geheimnis, userId) jest nadal przyjmowana jako potwierdzona, ale nie jako świeża – na potrzeby historii rozmowy i wyświetlania w panelu wystarcza, do danych klientów nie. Przestaw istniejące wdrożenia na formę z exp.
Gdy weryfikacja się nie powiedzie
Czat działa dalej, ale anonimowo. Widżet dostaje błąd auth_failed z przyczyną w detail.reason:
- no_hash – brakuje
userHash. - no_secret – dla projektu nie skonfigurowano sekretu.
- bad_exp –
expnie jest prawidłową liczbą całkowitą w sekundach (często: przekazano milisekundy). - expired –
expleży w przeszłości (strona długo otwarta, zły zegar serwera). - exp_too_far –
expleży ponad 24 godziny naprzód. - bad_hash – hash nie pasuje: zły sekret, zła kolejność,
userIdpodpisany jako liczba zamiast ciągu znaków, e-mail zapisany inaczej.
W zakładce „Sieć” narzędzi deweloperskich przyczyna widnieje w ramce error połączenia WebSocket; init_ok.identity pokazuje verified i reason.
Ustawienia „wpuszczaj tylko potwierdzonych odwiedzających” nie ma: niepotwierdzeni odwiedzający zawsze czatują jako anonimowi.
Rotacja sekretu
- Utwórz nowy sekret: dotychczasowy obowiązuje jeszcze przez 24 godziny. W tym czasie wpisz nowy na swoich serwerach.
- Usuń sekret: unieważnia od razu oba. Wszyscy użytkownicy uchodzą wtedy za niepotwierdzonych, dopóki nie skonfigurujesz nowego sekretu.
Zmiana użytkownika i wylogowanie
- Jeśli wywołasz
identifyz innym użytkownikiem (np. po zmianie konta w SPA), widżet oddziela wersję roboczą wiadomości od poprzedniego użytkownika. - Osobnego polecenia do wylogowania nie ma. Tożsamość obowiązuje tylko dla bieżącego otwarcia strony: po wylogowaniu serwuj strony bez
identify. Rozmowa i identyfikator odwiedzającego pozostają w przeglądarce; jeśli współdzielone urządzenie nie ma już niczego pokazywać, odwiedzający może usunąć swoje dane w widżecie.
Przekazywanie kontekstu
Oprócz tożsamości twoja strona może powiedzieć asystentowi i twojemu zespołowi, o co właśnie chodzi – np. jaki produkt jest wyświetlany albo co leży w koszyku. Służy do tego track:
ReactiveChat('track', 'warenkorb', {
page_type: 'cart',
cart_value: 129.80,
cart_items: 3,
currency: 'EUR'
});
Przejmowane są tylko te pola; wszystko inne jest odrzucane:
- Strona:
url,path,title,referrer,page_type,landing_path - Produkt:
product_id,variant_id,category,price,currency,in_stock - Koszyk:
cart_value,cart_items - Kampania:
utm_source,utm_medium,utm_campaign,gclid,msclkid,fbclid - Sygnały:
intent,intent_confidence,rage_score,scroll_pct,dwell_ms
Adres, tytuł, źródło wejścia i parametry kampanii widżet i tak rejestruje sam przy każdej zmianie strony. Kontekst jest przesyłany tylko za zgodą (Ochrona danych). Nie wpisuj w te pola danych osobowych – do tego służy identify.
Aplikacje mobilne
W aplikacji przekazujesz tożsamość po załadowaniu WebView przez JavaScript, nigdy przez adres. Hash także tutaj jest obliczany na twoim serwerze, a nie w aplikacji: Aplikacje mobilne.
Viimati uuendatud: