Pretius: strategiczna fuzja jako odpowiedź na współczesne wyzwania
Pretius. Budujemy mądrzej:
strategiczna fuzja jako odpowiedź na współczesne wyzwania

Linki do aplikacji APEX – Jak nie stracić aktywnej sesji

Kamil Rybicki

Oracle APEX Developer

  • 23 czerwca, 2022

Spis

[Uwaga] Ten artykuł został pierwotnie przygotowany w języku angielskim i został przetłumaczony na język polski.

Wylogowywanie się z aktywnej sesji aplikacji APEX może być czasami frustrujące dla użytkowników, którzy – na przykład – klikają w link do aplikacji będący częścią wiadomości e-mail. Użytkownicy chcieliby uniknąć ponownego logowania podczas otwierania linku do aplikacji. Idealnie byłoby również, gdyby mogli pracować w kilku kartach przeglądarki jednocześnie, nie martwiąc się o nadpisanie stanu sesji (session state). W tym artykule pokażę, jak tworzyć linki, które pozwolą na pracę w aktywnej sesji aplikacji APEX i w razie potrzeby jej sklonowanie (cloning).

Aktywna sesja APEX – zdefiniowanie problemu

Domyślnie na jednego klienta przeglądarki i aplikację APEX przypada tylko jedna sesja APEX (istnieje również funkcja udostępniania sesji, która pozwala na współdzielenie sesji w kilku aplikacjach w oparciu o pliki cookie, ale dla uproszczenia nie będę tutaj poruszać tego tematu).

Jest to duży problem, gdy chcesz wysłać link do aplikacji lub konkretnych stron w aplikacji za pośrednictwem poczty e-mail lub komunikatora. Domyślnie użytkownik zostanie wylogowany z aktywnej sesji po kliknięciu w link udostępniony przez inną osobę. Zazwyczaj dzieje się tak dlatego, że link wysłany przez inną osobę zawiera Session ID inny niż ID aktywnej sesji użytkownika klikającego w link. Zdarzają się również sytuacje, w których link nie zawiera żadnego Session ID. W obu przypadkach użytkownik zostanie wylogowany, co może być dość frustrujące dla osób, które lubią pracować w ramach tej samej sesji i najlepiej w kilku kartach.

Na szczęście istnieje sposób na obejście tego problemu. Chcesz wiedzieć jaki? Czytaj dalej!

Ustawienie Rejoin Sessions

Zanim przejdę do konkretnych problemów i ich rozwiązań wraz z przykładami, muszę wspomnieć o kwestii, która będzie wspólna i wymagana dla każdego z problemów opisanych w tym artykule – Rejoin Sessions.

Aby w ogóle móc mówić o korzystaniu z istniejącej sesji użytkownika, konieczne jest ustawienie opcji Rejoin Sessions na wartość Enabled for All Sessions na poziomie aplikacji (Shared Components -> Security Attributes -> zakładka Session Management) lub konkretnej strony w sekcji Security. Gdy to ustawienie zostanie ustawione na wspomnianą wartość, APEX zacznie używać plików cookie do korzystania z istniejącej sesji.

Warto zauważyć, że ustawienie Rejoin Sessions na poziomie aplikacji lub strony APEX jest nadpisywane przez ustawienia na poziomie instancji APEX (Manage Instance -> Security -> zakładka Security). Oznacza to, że jeśli Rejoin Sessions na poziomie instancji jest ustawione na Disabled, nie będzie można zmienić tego ustawienia na poziomie aplikacji.

Kwestie bezpieczeństwa

Dodatkowo, zmiana ustawienia Rejoin Sessions naraża aplikację na naruszenia bezpieczeństwa. Poniżej znajduje się cytat z tekstu pomocy dla ustawienia Rejoin Sessions:

„Włączenie ponownego dołączania do sesji (rejoin sessions) naraża aplikację na możliwe naruszenia bezpieczeństwa, ponieważ może umożliwić atakującym przejęcie istniejących sesji użytkowników końcowych. Aby dowiedzieć się więcej, zapoznaj się z sekcjami Rejoin Sessions w rozdziale „Managing Application Security” w App Builder User’s Guide”.

Dlatego jeśli chcesz zezwolić na Rejoin Sessions, powinieneś najpierw zadbać o bezpieczeństwo swojego systemu.

Przypadek 1 – linki bez parametrów

Przejdźmy więc do konkretnych przypadków, które zaprezentuję i omówię na przykładzie nieco zmodyfikowanej aplikacji Customers dostępnej w Apps Gallery. W każdym przykładzie stworzę APEX item zawierający odpowiedni link, który mógłby zostać użyty w wiadomości e-mail.

Pierwszy przypadek, który opiszę, dotyczy linków bez parametrów – jest to najprostszy z omawianych przykładów. Linki tego rodzaju są również stosunkowo bezpieczne, ponieważ nie przekazują wartości, które mogłyby zostać podmienione, powodując dostęp do danych, których użytkownik nie powinien widzieć.

Linki bez parametrów mogą być przydatne – na przykład – jeśli chcemy wysyłać e-maile o powiadomieniach w aplikacjach dostępnych pod ikoną dzwonka na górnym pasku nawigacyjnym. W takiej sytuacji zazwyczaj chcemy skierować użytkownika do odpowiedniej aplikacji/środowiska, w którym powinien zostać powiadomiony. Taki link zazwyczaj prowadzi do strony głównej i nie ma żadnych parametrów.

Przejdźmy więc do implementacji powyższego przykładu. Na Stronie 59 (Customers), ustawiam atrybut Rejoin Sessions w sekcji Security na Enabled for All Sessions.

Ekran pokazujący ustawienia APEX.

W następnym kroku buduję link do strony głównej mojej aplikacji, który mógłby zostać wykorzystany przy wysyłaniu e-maila. W moim przykładzie po prostu utworzę region i APEX item, który będzie wyświetlał URL do strony Customers. Dodaję więc APEX item o nazwie „P59_HOME_URL” i w sekcji Default wpisuję następujące wyrażenie PL/SQL Expression:

APEX_UTIL.HOST_URL || APEX_UTIL.PREPARE_URL(p_url => 'f?p=' || :APP_ID || ':59')

Ekran pokazujący wyrażenie PL/SQL.

Spowoduje to wygenerowanie adresu URL (zauważ, że nie zawiera on Session ID), który po wpisaniu w pasku przeglądarki nie wyloguje użytkownika z aktywnej sesji, ponieważ APEX użyje istniejącego ciasteczka sesji (session cookie) dla tej aplikacji.

Ekran pokazujący stronę klientów.

Przypadek 2 – linki z parametrami

Drugi przykład, który chciałbym zaprezentować, dotyczy linków z parametrami. W tym przypadku należy zadbać o bezpieczeństwo, aby uniknąć zmiany parametrów w linku, co mogłoby skutkować dostępem użytkowników do informacji, których nie powinni widzieć.

Linki z parametrami mogą być wykorzystywane w sytuacji, gdy chcemy przekierować użytkownika na konkretną stronę. Może to być np. prezentacja szczegółów zamówienia złożonego w naszej aplikacji (sklepie internetowym) lub danych klienta i wszystkich powiązanych z nimi informacji. W obu przypadkach link powinien prowadzić bezpośrednio do danych, które interesują osobę klikającą w link, bez konieczności przeszukiwania dużej liczby wierszy w poszukiwaniu odpowiedniego klienta/zamówienia.

W moim drugim przykładzie użyję strony prezentującej informacje o kliencie. Na Customer page (strona 50), podobnie jak na stronie 59, ustawiam atrybut Rejoin Sessions w sekcji Security na Enabled for All Sessions. Tym razem nie będzie to takie proste, ponieważ linki z atrybutami wymagają następujących elementów:

  • ustawienia Session State Protection na Enabled na poziomie ustawień aplikacji (Shared Components -> Security Attributes -> zakładka Session State Protection);
  • URL z parametrami musi posiadać poprawny checksum (sumę kontrolną).

Jeśli którykolwiek z tych warunków nie zostanie spełniony, użytkownik nie zostanie przekierowany na odpowiednią stronę przy użyciu istniejącej sesji.

W przypadku mojego przykładu, Session State Protection jest włączone. Dodatkowo mam atrybut Page Access Protection ustawiony na Arguments Must Have Checksum, aby zapobiec dostępowi do danych, jeśli nie zostanie podany poprawny checksum. Pozostaje więc zadbać jedynie o poprawny checksum w URL. Podobnie jak na stronie 59, dodam nowy region i stworzę APEX item o nazwie „P50_URL_WITH_PARAM”, aby wyświetlić link. Wartość itemu ustawiam za pomocą następującego wyrażenia PL/SQL Expression (opis parametrów i typów checksum znajdziesz poniżej, w podrozdziale o funkcji APEX_UTIL.PREPARE_URL):

APEX_UTIL.HOST_URL || APEX_UTIL.PREPARE_URL(

    p_url => 'f?p=' || :APP_ID || ':50::::50:P50_ID:' || :P50_ID,

    p_checksum_type => 'PUBLIC_BOOKMARK',

    p_plain_url => true

)

Ekran pokazujący edytor kodu.

Nasz link jest praktycznie gotowy. Ostatnim krokiem jest zmiana atrybutu Session State Protection elementu „P50_ID” na Checksum Required – Application Level. Zmiana ta jest konieczna, jeśli typ checksum zbudowanego linku jest ustawiony na PUBLIC_BOOKMARK.

Gotowe! Czas na testy. Załóżmy, że częścią aplikacji, nad którą obecnie pracuję, jest strona Partners (górne okno na zrzucie ekranu poniżej). W trakcie pracy otrzymuję e-mail o zmianach na stronie klienta Illumina Biotech (np. dodano nową aktywność) wraz z linkiem do strony szczegółów klienta (URL zawarty w itemie „P50_URL_WITH_PARAM”), abym mógł szybko się tam przenieść. Po kliknięciu w link zostanę przekierowany do szczegółów klienta bez utraty istniejącej sesji (dolne okno na zrzucie ekranu poniżej).

Ekran pokazujący stronę partnerów.

Warto zauważyć, że link, który docelowo zostałby użyty – np. w wiadomości e-mail – nie posiada numeru sesji, ponieważ nie jestem w stanie przewidzieć, jaki będzie Session ID użytkownika klikającego w link, ani nie wiem, kiedy link zostanie kliknięty. Umieszczenie Session ID w linku spowodowałoby wylogowanie użytkownika, gdyby ID było inne niż to, które użytkownik posiada w aktywnej sesji, a tego chcę uniknąć.

APEX_UTIL.PREPARE_URL – parametry funkcji i typy checksum

Zgodnie z dokumentacją, funkcja PREPARE_URL z pakietu APEX_UTIL zawiera następujące parametry:

  • p_url – adres URL nawigacji APEX. Można tu określić stronę docelową oraz nazwy i wartości APEX itemów, które chcemy ustawić;
  • p_url_charset – nazwa zestawu znaków. W moim przykładzie używam wartości domyślnej;
  • p_checksum_type – typ checksum. Najważniejszy parametr w kontekście unikania wylogowania z aktywnej sesji. Wartością domyślną jest null, ale może on przyjmować również inne wartości:
    • PUBLIC_BOOKMARK lub 1 – użyj tej wartości, gdy chcesz wygenerować link, który będzie dostępny dla wszystkich użytkowników, jak ten używany w wiadomości e-mail. Nie jest on powiązany z sesją użytkownika ani z użytkownikiem, który generuje link.
      • Oznacza to, że jeśli użytkownik Marek wygeneruje taki link, może go z powodzeniem wysłać do użytkownika Samuela, a kliknięcie Samuela w link nie spowoduje jego wylogowania z aktywnej sesji (zakładając, że warunki z sekcji Linki z parametrami zostały spełnione).
  • PRIVATE_BOOKMARK lub 2 – użyj tej wartości, gdy chcesz wygenerować prywatny link, który będzie dostępny tylko dla Ciebie. Jest on powiązany z aktualnie uwierzytelnionym użytkownikiem.
    • Oznacza to, że jeśli Marek wygeneruje taki link i go zapisze, będzie mógł w niego kliknąć za kilka dni i to kliknięcie nie wyloguje go z aktywnej sesji APEX. Jeśli natomiast wyśle ten link do Samuela, Samuel zostanie wylogowany ze swojej aktywnej sesji, ponieważ link wysłany przez Marka jest prywatny.
  • SESSION lub 3 – ostatnia wartość jest używana, gdy chcesz uniknąć wylogowania z sesji, która była aktywna w momencie tworzenia linku. Jest ona powiązana z aktywną sesją użytkownika w momencie tworzenia linku.
    • Oznacza to, że jeśli Marek wygeneruje taki link dla siebie, będzie mógł z niego korzystać do czasu wygaśnięcia aktywnej sesji – kliknięcie w link nie wyloguje Marka. Jeśli natomiast Marek wygeneruje link przy aktywnej sesji numer 1, następnie wyloguje się z aplikacji i zaloguje ponownie (utworzy sesję numer 2), to kliknięcie w link wyloguje Marka z sesji numer 2, ponieważ link został utworzony w sesji numer 1.
  • p_triggering_element – selektor jQuery. Jest to wymagane dla obsługi Modal Dialog. W moim przypadku używam wartości domyślnej;
  • p_plain_url – flaga wskazująca, czy należy dodać kod JavaScript w przypadku wywołania funkcji z poziomu okna modalnego. W moim przypadku ustawiam tę wartość na true, ponieważ chcę uniknąć dodawania dodatkowego kodu JavaScript, gdyż wywołuję tę funkcję ze zwykłej strony.

Przypadek 3 – linki z parametrami i Session Cloning

Klonowanie sesji APEX (Session Cloning) to ostatni przykład, który chciałbym zaprezentować. Jest to również rozszerzenie tematu linków z parametrami. Session cloning pomaga uniknąć problemu nadpisywania wartości itemów w sesji poprzez skopiowanie ich bieżącej wartości do nowej sesji. Dzięki temu użytkownicy aplikacji mogą pracować na kilku kartach jednocześnie.

Session cloning z pewnością przydałoby się w opisywanej powyżej sytuacji w sekcji linków z parametrami. Przykładowo użytkownik, który uzyskuje dostęp do danych klienta lub informacji o konkretnym zamówieniu, chciałby uniknąć nadpisania danych o innym kliencie/zamówieniu, który jest otwarty w innej karcie. Session cloning daje taką możliwość.

Aby sklonować sesję APEX, konieczne jest ustawienie parametru CLONE_SESSION_ENABLED na Y na poziomie instancji APEX. Więcej informacji można znaleźć w oficjalnej dokumentacji.

Przejdźmy zatem do ostatniego przykładu, w którym wykorzystam tę samą stronę, której użyłem w przypadku 2 – tę prezentującą informacje o kliencie.

Najpierw na Global Page tworzę region o nazwie „Global items container”, ustawiam jego Template na Blank with Attributes i wewnątrz tego regionu tworzę APEX item typu Hidden o nazwie „P0_CLONE_SESSION”. Na koniec ustawiam atrybut Session State Protection elementu „P0_CLONE_SESSION” na Checksum Required – Application Level.

Ekran pokazujący App Builder.

W tym momencie mam gotowy APEX item, który będzie flagą informującą o tym, czy sklonować sesję APEX (np. przy kliknięciu w link będący częścią maila, który otwiera stronę aplikacji w nowej karcie), czy nie.

Kolejnym krokiem jest stworzenie procesu odpowiedzialnego za klonowanie sesji w momencie, gdy wartość encji „P0_CLONE_SESSION” jest równa Y.

Na Customer page (50), w sekcji Pre-Rendering i podsekcji Before Header, tworzę proces o nazwie „Clone APEX session”. W sekcji Server-side Condition ustawiam Type na Item = Value. W polu Item wpisuję wartość „P0_CLONE_SESSION”, a w polu Value wartość Y. Następnie podaję poniższy kod PL/SQL, który zostanie wykonany przez proces:

  :P0_CLONE_SESSION := 'N'; -- Set 'N' for current (not cloned) session




    APEX_UTIL.REDIRECT_URL(

        p_url => APEX_UTIL.HOST_URL || APEX_UTIL.PREPARE_URL( 

                    p_url           => 'f?p=' || :APP_ID || ':50:SESSION:APEX_CLONE_SESSION::50:P0_CLONE_SESSION,P50_ID:N,' || :P50_ID,

                    p_checksum_type => 'PUBLIC_BOOKMARK',

                    p_plain_url     => true

                )  || '&session=' || :APP_SESSION

    );

end;

Ekran pokazujący edytor kodu.

Następnie duplikuję APEX item o nazwie „P50_URL_WITH_PARAM” i ustawiam nazwę zduplikowanego itemu na „P50_URL_WITH_PARAM_AND_CLONE”. W tym itemie wyświetlę link, który – w połączeniu ze zdefiniowanym powyżej procesem – oprócz przekierowania na stronę docelową, sklonuje sesję. Wartość tego elementu ustawiam za pomocą następującego wyrażenia PL/SQL Expression:

APEX_UTIL.HOST_URL || APEX_UTIL.PREPARE_URL( 

    p_url           => 'f?p=' || :APP_ID || ':50::::50:P0_CLONE_SESSION,P50_ID:Y,' || :P50_ID,

    p_checksum_type => 'PUBLIC_BOOKMARK',

    p_plain_url     => true

)

Dodatkowo dodaję APEX item o nazwie P50_SESSION_ID, który pokaże mi Session ID.

Gotowe! Zanim przejdę do testów, wyjaśnię jeszcze raz, jak działa to rozwiązanie. APEX item o nazwie „P50_URL_WITH_PARAM_AND_CLONE” przechowuje link do strony docelowej (w mojej aplikacji są to dane klienta). Link ten mógłby zostać użyty np. w wiadomości e-mail. Poza ID klienta, którego dane chcę wyświetlić, zawiera on „flagę” o wartości Y dla elementu „P0_CLONE_SESSION”. Spowoduje to uruchomienie procesu klonującego sesję, ponieważ warunek w Server-side Condition zostanie spełniony. Proces ten przekieruje na tę samą stronę z żądaniem APEX_CLONE_SESSION, co sklonuje sesję, ale tylko wtedy, gdy w linku podany jest numer sesji. Dlatego dołączyłem numer sesji na końcu linku – ponieważ funkcja APEX_UTIL.PREPARE_URL automatycznie by się go pozbyła. Po przekierowaniu sesja jest klonowana.

Czas na testy. Loguję się do aplikacji i zostaje mi przypisany Session ID 15637848892753. Wchodzę na stronę klienta Illumina Biotech i kopiuję link wygenerowany przez element o nazwie „P50_URL_WITH_PARAM_AND_CLONE” (górne okno przeglądarki na zrzucie ekranu poniżej). Wklejam ten link w nowej karcie spodziewając się wyświetlenia tych samych danych klienta, ale w sklonowanej sesji APEX (dolne okno przeglądarki na zrzucie ekranu poniżej).

Ekran pokazujący stronę klientów.

Udało się! Sesja została sklonowana, więc użytkownik może bezpiecznie modyfikować dane bez obawy o nadpisanie wartości itemów, co miałoby miejsce w przypadku współdzielonej sesji.

Adnotacje

  • Ten artykuł opiera się na wersji APEX 21.2 z włączonym ustawieniem Friendly URLs. Jeśli korzystasz z innej wersji APEX, która nie obsługuje Friendly URLs, może być konieczne dostosowanie powyższych przykładów do Twojej wersji APEX i problemu, który próbujesz rozwiązać.
  • Sprawdź również, czy w Twoim konkretnym przypadku funkcja APEX_UTIL.HOST_URL nie wymaga odpowiedniej wartości parametru, aby przygotowany link działał bez problemów.

Aktywna sesja APEX – podsumowanie

Jak widać, istnieją sposoby, które można wykorzystać do rozwiązywania problemów z sesjami i zapobiegania konieczności ponownego logowania się użytkowników po otwarciu linku do aplikacji. Co więcej, ich wdrożenie naprawdę nie jest trudne. Przy odrobinie czasu i pracy możesz skonfigurować aplikację tak, jak chcesz.

Warto zaznaczyć, że w APEX 22.1 dostępna jest również funkcja o nazwie Persistent Authentication, która powinna rozwiązać przynajmniej część problemów opisanych w tym artykule. Nie miałem jeszcze okazji jej przetestować, ale na pewno zrobię to niedługo i podzielę się wrażeniami w kolejnym wpisie na blogu!

Jeśli interesują Cię treści związane z APEX, sprawdź inne artykuły na naszym blogu:

  1. How to integrate Stripe with an Oracle APEX application: Step-by-step guide
  2. Oracle APEX new features – the low-code platform keeps evolving
  3. Google Identity Services – a quick guide on using the new library in Oracle APEX applications
  4. What is Oracle APEX? Possibilities and career paths for low-code developers

Szukasz firmy tworzącej oprogramowanie?

Pracuj z zespołem, który pomógł już dziesiątkom rynkowych liderów. Umów spotkanie, by dowiedzieć się:

  • Jak działają nasze produkty
  • Jak możesz oszczędzić czas i pieniądze
  • Czym nasze rozwiązania różnią się od konkurencji

Przebieg kontaktu z Pretius

Dbamy o bezpieczeństwo Twoich danych: Certyfikat ISO

Działamy zgodnie z normą ISO 27001, zapewniając najwyższy poziom bezpieczeństwa Twoich danych.
certified dekra 27001
© 2026 Pretius. All right reserved.