Po przesłaniu przez nowego użytkownika formularza „Nowe konto” chcę ręcznie zalogować tego użytkownika, aby nie musiał się logować na kolejnej stronie.
Normalna strona logowania do formularza przechodząca przez przechwytywacz zabezpieczenia sprężyny działa dobrze.
W kontrolerze formularza nowego konta tworzę UsernamePasswordAuthenticationToken i ustawiam go ręcznie w SecurityContext:
SecurityContextHolder.getContext().setAuthentication(authentication);
Na tej samej stronie później sprawdzam, czy użytkownik jest zalogowany:
SecurityContextHolder.getContext().getAuthentication().getAuthorities();
Powoduje to zwrócenie uprawnień, które ustawiłem wcześniej podczas uwierzytelniania. Wszystko dobrze.
Ale kiedy ten sam kod jest wywoływany na następnej ładowanej stronie, token uwierzytelniający jest po prostu UserAnonymous.
Nie jestem pewien, dlaczego nie zachował uwierzytelnienia, które ustawiłem w poprzednim żądaniu. jakieś pomysły?
- Czy może to mieć coś wspólnego z nieprawidłowym skonfigurowaniem identyfikatora sesji?
- Czy jest coś, co prawdopodobnie nadpisuje moje uwierzytelnienie?
- Może potrzebuję tylko kolejnego kroku, aby zapisać uwierzytelnienie?
- A może jest coś, co muszę zrobić, aby w jakiś sposób zadeklarować uwierzytelnianie w całej sesji zamiast pojedynczego żądania?
Szukam tylko myśli, które pomogą mi zobaczyć, co się tutaj dzieje.
źródło
SecurityContextHolder.getContext().setAuthentication(authentication)
. To działa i jest powszechne, ale istnieją poważne wady w funkcjonalności, które napotkasz, jeśli to zrobisz. Aby uzyskać więcej informacji, zobacz moje pytanie i odpowiedź: stackoverflow.com/questions/47233187/…Odpowiedzi:
Miałem ten sam problem co ty jakiś czas temu. Nie pamiętam szczegółów, ale poniższy kod sprawił, że wszystko działało. Ten kod jest używany w przepływie Spring Webflow, stąd klasy RequestContext i ExternalContext. Jednak najbardziej istotną częścią jest metoda doAutoLogin.
źródło
@Configuration public class WebConfig extends WebSecurityConfigurerAdapter { @Bean @Override public AuthenticationManager authenticationProvider() throws Exception { return super.authenticationManagerBean(); } }
Nie mogłem znaleźć innych pełnych rozwiązań, więc pomyślałem, że opublikuję swoje. To może być trochę hackowanie, ale rozwiązało problem powyższego problemu:
źródło
authenticationManager
od?Ostatecznie odkryłem źródło problemu.
Gdy ręcznie tworzę kontekst zabezpieczeń, nie jest tworzony żaden obiekt sesji. Dopiero po zakończeniu przetwarzania żądania mechanizm Spring Security zdaje sobie sprawę, że obiekt sesji jest pusty (gdy próbuje zapisać kontekst bezpieczeństwa w sesji po przetworzeniu żądania).
Pod koniec żądania Spring Security tworzy nowy obiekt sesji i identyfikator sesji. Jednak ten nowy identyfikator sesji nigdy nie trafia do przeglądarki, ponieważ pojawia się na końcu żądania, po udzieleniu odpowiedzi przeglądarce. Powoduje to utratę nowego identyfikatora sesji (a tym samym kontekstu zabezpieczeń zawierającego mojego ręcznie zalogowanego użytkownika), gdy następne żądanie zawiera identyfikator poprzedniej sesji.
źródło
Włącz rejestrowanie debugowania, aby uzyskać lepszy obraz tego, co się dzieje.
Możesz sprawdzić, czy pliki cookie sesji są ustawiane, używając debugera po stronie przeglądarki do przeglądania nagłówków zwracanych w odpowiedziach HTTP. (Są też inne sposoby.)
Jedną z możliwości jest to, że SpringSecurity ustawia pliki cookie sesji bezpiecznej, a następna żądana strona ma adres URL „http” zamiast adresu URL „https”. (Przeglądarka nie wyśle bezpiecznego pliku cookie dla adresu URL „http”).
źródło
Nowa funkcja filtrowania w Servlecie 2.4 zasadniczo łagodzi ograniczenie, że filtry mogą działać tylko w przepływie żądań przed i po rzeczywistym przetworzeniu żądania przez serwer aplikacji. Zamiast tego, filtry Servlet 2.4 mogą teraz współdziałać z dyspozytorem żądań w każdym punkcie wysyłania. Oznacza to, że gdy zasób WWW przekazuje żądanie do innego zasobu (na przykład serwlet przekazujący żądanie do strony JSP w tej samej aplikacji), filtr może działać, zanim żądanie zostanie obsłużone przez docelowy zasób. Oznacza to również, że jeśli zasób sieciowy zawiera dane wyjściowe lub funkcję z innych zasobów sieci Web (na przykład strona JSP zawierająca dane wyjściowe z wielu innych stron JSP), filtry Servlet 2.4 mogą działać przed i po każdym z uwzględnionych zasobów. .
Aby włączyć tę funkcję, potrzebujesz:
web.xml
RegistrationController
źródło
Próbowałem przetestować aplikację extjs i po pomyślnym ustawieniu testingAuthenticationToken nagle przestało działać bez wyraźnej przyczyny.
Nie udało mi się uzyskać powyższych odpowiedzi, więc moim rozwiązaniem było pominięcie tej wiosny w środowisku testowym. W okolicach wiosny wprowadziłem szew w ten sposób:
Użytkownik jest tutaj typem niestandardowym.
Następnie opakowuję go w klasę, która ma tylko opcję przełączania kodu testowego.
Wersja testowa wygląda tak:
W kodzie wywołującym nadal używam właściwego użytkownika załadowanego z bazy danych:
Oczywiście nie będzie to odpowiednie, jeśli faktycznie potrzebujesz użyć zabezpieczeń, ale używam konfiguracji bez zabezpieczeń do wdrożenia testowego. Myślałem, że ktoś inny może znaleźć się w podobnej sytuacji. To jest wzorzec, którego użyłem wcześniej do wyśmiewania statycznych zależności. Inną alternatywą jest zachowanie statyczności klasy opakowania, ale ja wolę tę, ponieważ zależności kodu są bardziej wyraźne, ponieważ musisz przekazać CurrentUserAccessor do klas, w których jest to wymagane.
źródło