Dlaczego WARs nie może udostępniać informacji o sesji?

11

Widziałem kilku programistów szukających rozwiązania tego problemu: uzyskiwanie dostępu do informacji o sesji z innej WAR (nawet gdy znajduje się w tym samym pliku EAR) - oto kilka przykładów: Jak można udostępnić stan sesji między różnymi aplikacjami w tomcat? , Sesja dostępu do innej aplikacji internetowej , różne pliki WAR, udostępnione zasoby , Tomcat: jak współdzielić dane między dwiema aplikacjami? , Co robi atrybut crossContext w Tomcat? Czy umożliwia udostępnianie sesji? i tak dalej...

Ze wszystkiego, co szukałem, istnieją pewne konkretne rozwiązania w zależności od pojemnika, ale jest to w jakiś sposób „ sprzeczne ze specyfikacją ”. Przejrzałem także specyfikację Java EE, ale bez powodzenia w znalezieniu odpowiedzi.

Niektórzy programiści mówią o sprzężeniu między aplikacjami internetowymi, ale zwykle się nie zgadzam. Jaki jest powód, dla którego WOF trzymane byłyby w tym samym EAR, gdyby nie były sprzężone? Na przykład do EJB można uzyskać dostęp lokalnie (nawet jeśli znajduje się w innym pliku JAR EJB w tym samym pliku EAR).

Mówiąc dokładniej, jedna z moich WAR obsługuje uwierzytelnianie i autoryzację, i chciałbym udostępnić te informacje innym WAR (w tym samym EAR). Wcześniej udało mi się obejść podobne problemy, pakując WARs jako JAR i umieszczając je w jednym projekcie WAR (WEB-INF / lib). Jednak nie podoba mi się to rozwiązanie (wymaga ogromnego wysiłku nazywania serwletów i tak dalej).

I żadne rozwiązanie nie odpowiedziało na pierwsze (i najważniejsze) pytanie: Dlaczego WARs nie może udostępniać informacji o sesji?

rvcoutinho
źródło
1
Nie jestem pewien, dlaczego zostało to odrzucone, inne niż może być lepsze dla SO.
NateDSaint,
3
„Zgodnie ze specyfikacją interfejsu API serwletu 2.3 menedżer sesji obsługuje zakres sesji tylko przez moduł sieciowy. Tylko serwlety w tym samym module sieciowym mają dostęp do danych powiązanych z określoną sesją.” Można to ponownie zobaczyć w HttpSession - „Informacje o sesji dotyczą tylko bieżącej aplikacji WWW (ServletContext), więc informacje przechowywane w jednym kontekście nie będą bezpośrednio widoczne w innym”. - Takie postępowanie jest niezgodne ze specyfikacją.
(lepiej, aktualny link do HttpSession )
@MichaelT, dziękuję. Ale nadal nie odpowiada dlaczego.
rvcoutinho
@NateDSaint Chociaż pytanie dotyczy konkretnych technologii, uważałem, że bardziej prawdopodobne jest pytanie koncepcyjne. Potem zdecydowałem się na programistów.
rvcoutinho,

Odpowiedzi:

7

Traktuj EAR jak maszynę pseudo-wirtualną

Plik EAR to po prostu zbiór plików WAR, które mają wspólną konfigurację i biblioteki, zwykle z plików JAR. Umożliwia to łatwiejsze zarządzanie zestawem usług zależnych w kontenerze aplikacji. Dlatego można myśleć o EAR jako o prostej formie maszyny wirtualnej po wdrożeniu w jej kontenerze.

W ten sam sposób, w jaki jeden proces na maszynie wirtualnej nie może wpływać na inny, to samo dotyczy EAR. Wszystkie WAR są izolowane, aby chronić ich stan wewnętrzny.

Skalowanie uwierzytelnienia

Zasadniczo aplikacje internetowe muszą być bezstanowe, aby można je było dobrze skalować. Posiadanie dużej ilości informacji w sesji jest anty-wzorcem, który temu zapobiega. Prowadzi to do konfliktu między bezstanowym charakterem HTTP a potrzebą zachowania szybkiego, dostosowanego do potrzeb użytkownika. Uwierzytelnianie jest klasycznym przypadkiem użycia i jest powszechne w gadatliwych interfejsach API, które wymagają wielu uwierzytelnionych żądań w celu zapewnienia funkcjonalności dla użytkownika końcowego.

Pojedyncze logowanie i pojedyncze logowanie wymagają starannej sygnalizacji, aby działać poprawnie (rozważ częściowe wylogowanie), szczególnie gdy jest stosowane skalowanie poziome. Po prostu udostępnianie stanu sesji prawie nigdy nie jest dobrym rozwiązaniem, a lepszym podejściem jest użycie jednego punktu odniesienia dla informacji o użytkowniku, do których mają dostęp wszystkie węzły w klastrze.

Skoncentrowanie się na szybkim dostępie do odpowiednich informacji w pamięci podręcznej przyniesie znacznie bardziej skalowalne wyniki niż niektóre złożone, delikatne rozwiązanie do udostępniania sesji.

Gary Rowe
źródło
Dzięki, @GaryRowe. Oto odpowiedź, której szukałem. W każdym razie, czy to nie może być decyzja dewelopera?
rvcoutinho
Kolejne pytanie: czy uważasz, że JBoss Cache może być dobrym rozwiązaniem? Czy słyszałeś o Apache Shiro (i klastrowaniu sesji)? Co z tym?
rvcoutinho
@rvcoutinho Czy twórca aplikacji decyduje o sposobie zarządzania procesami w jądrze systemu Linux? To podobne sformułowanie pytania - tak, możesz to zrobić, ale będzie bardzo trudne i prawdopodobnie spowoduje więcej bólu niż pójście alternatywną ścieżką.
Gary Rowe,
2
@rvcoutinho Nie korzystałem z Apache Shiro (alias Apache Security), ale wyobrażam sobie, że byłoby to dobre rozwiązanie wspólnego problemu bezpieczeństwa. Zdecydowanie rozważ integrację z OpenID i OAuth2 zamiast rozwijania własnego protokołu w celu osiągnięcia tego samego. JBoss Cache jest, według własnego uznania, w ślepym zaułku zastąpiony Infinispanem, który wygląda raczej skomplikowanie. Możesz rzucić okiem na stronę aplikacji dwunastostopniowej, aby zobaczyć prostsze, bardziej skalowalne rozwiązanie.
Gary Rowe,
2

Wydaje mi się, że brakuje w tym specyfikacji funkcjonalności JEE EAR - możliwości udostępniania sesji internetowych w wielu archiwach internetowych powiązanych w pliku EAR.

Serwery aplikacji, takie jak Weblogic, mają implementacje niestandardowe dla tej funkcji.

Martijn Verburg
źródło
To była moja opinia do tej pory. Próbowałem zrozumieć, dlaczego dokonano wspomnianego wyboru.
rvcoutinho,
1

AFAIKS, nie ma prawdziwego powodu, dla którego chciałbyś to zrobić. WAR to niezależna aplikacja internetowa z własnymi zakresami (specyficznymi dla aplikacji internetowych) (np. Zasięg sesji). Jeśli chcesz współdzielić funkcje (kod Java, strony JSP, pliki CSS), pomiędzy wieloma WARami masz o wiele bardziej sensowną opcję pakowania ich jako plików JAR i wdrażania ich na serwerze aplikacji. Pakiet WAR jest bardziej złożonym rozwiązaniem do pakowania, zaprojektowanym tak, aby zawierało coś innego niż zwykły „wspólny kod / funkcjonalność”. JAR jest prostszym formatem ORAZ jest przeznaczony do pakowania i udostępniania kodu i funkcjonalności. Dlaczego chcesz korzystać z bardziej złożonego i niespecyficznie zaprojektowanego do tego opakowania, aby udostępnić coś, skoro masz już prostszy i bardziej odpowiedni format pakietu, który jest już dostępny.

Shivan Dragon
źródło
Zgadzam się z Tobą. Ale tylko w przypadku ogólnych zasobów. Ale w przypadku aplikacji do pojedynczego logowania musiałbym udostępnić informacje dotyczące sesji (dotyczące zalogowanego użytkownika). I nie widzę powodu, dla którego byłoby to niezgodne ze specyfikacją.
rvcoutinho
2
Ponieważ zakres sesji nie jest przeznaczony do udostępniania bieżących danych użytkownika między różnymi aplikacjami. A ponieważ logowanie jednokrotne oznacza więcej niż sprawdzanie atrybutów zakresu sesji. Możesz tworzyć i pakować kod poza wojną (który nie byłby zależny od twojej wojny, ale raczej by wojna zależała od niej), który uzyskałby dostęp do atrybutów zakresu sesji, gdybyś chciał (jak filtr), ale lepszym rozwiązaniem byłoby IMHO mieć osobną aplikację elewacyjną lub konfigurację serwera, która zajmuje się uwierzytelnianiem i zapewnia dostęp do innych aplikacji (wdrożonych podczas wojny).
Shivan Dragon,
Znowu się z tobą zgodzę. Jednak specyfikacja JavaEE (przy użyciu JAAS) przechowuje informacje o użytkowniku jako część HttpSession, co jest sprzeczne z tym podejściem. Jednym z powodów, dla których rozważałem użycie Shiro (utrzymuje sesję ortogonalną).
rvcoutinho,
W każdym razie dzięki za odpowiedź. Nadal nie mam ostatecznej odpowiedzi na moje pytanie, ale wszystko, co powiedziałeś, jest istotne. +1
rvcoutinho,
@ rvcoutinho cóż, to moja opinia w tej sprawie, przepraszam, że nie była dla ciebie bardziej pomocna.
Shivan Dragon,
0

Myślę, że zostało to zrobione celowo, aby uniknąć przypadkowego zastąpienia informacji o sesji przez różne aplikacje internetowe. Może się to przydać w twoim przypadku, ale ogólnie rzecz biorąc, nie chcesz, aby użytkownicy powodowali awarię aplikacji lub zwiększali swoje uprawnienia tylko dlatego, że korzystają z dwóch aplikacji internetowych jednocześnie. Bezpośrednie udostępnianie informacji między aplikacjami internetowymi nie jest trudne; po prostu stwórz klasę ze statyczną HashMap, użyj GUID jako kluczy i przenieś je jako część parametru URL lub HTTP.

użytkownik 281377
źródło
Dzięki. W rzeczywistości nie mówiłem o współużytkowaniu całej sesji między każdą aplikacją, ale konkretnych informacji o sesji (jako informacji o użytkowniku) w razie potrzeby. Może nie byłem jasny. Wszelkie sugestie, jak to uczynić?
rvcoutinho,