Styr sessionen med Spring Security

1. Oversigt

I denne artikel vil vi illustrere hvordan Spring Security giver os mulighed for at kontrollere vores HTTP-sessioner.

Denne kontrol spænder fra en sessionstimeout til aktivering af samtidige sessioner og andre avancerede sikkerhedskonfigurationer.

2. Hvornår oprettes sessionen?

Vi kan kontrollere nøjagtigt, hvornår vores session oprettes, og hvordan Spring Security vil interagere med den:

  • altid- en session oprettes altid, hvis en ikke allerede eksisterer
  • hvis nødvendigt- en session oprettes kun, hvis det kræves (Standard)
  • aldrig- rammen opretter aldrig en session selv, men den bruger en, hvis den allerede findes
  • statsløs- ingen session oprettes eller bruges af Spring Security
...

Java-konfiguration:

@ Override beskyttet ugyldig konfiguration (HttpSecurity http) kaster undtagelse {http.sessionManagement () .sessionCreationPolicy (SessionCreationPolicy.IF_REQUIRED)}

Det er meget vigtigt at forstå det denne konfiguration styrer kun, hvad Spring Security gør - ikke hele applikationen. Spring Security opretter muligvis ikke sessionen, hvis vi instruerer den ikke, men vores app kan!

Som standard, Spring Security opretter en session, når den har brug for en - dette er "hvis nødvendigt“.

Til en mere statsløs applikation, det "aldrig”Valgmulighed vil sikre, at Spring Security ikke selv opretter nogen session; Men hvis applikationen opretter en, så bruger Spring Security den.

Endelig er den strengeste mulighed for at oprette session - “statsløs" - er en garantere, at applikationen slet ikke opretter nogen session.

Dette blev introduceret i foråret 3.1 og vil effektivt springe dele over Spring Security filterkæden over - hovedsageligt de sessionrelaterede dele som f.eks HttpSessionSecurityContextRepository, SessionManagementFilter, RequestCacheFilter.

Disse mere strenge kontrolmekanismer har den direkte betydning, at cookies bruges ikke også hver anmodning skal godkendes igen. Denne statsløse arkitektur spiller godt med REST API'er og deres begrænsning af statsløshed. De fungerer også godt med godkendelsesmekanismer såsom grundlæggende og fordøjelsesgodkendelse.

3. Under hætten

Inden godkendelsesprocessen udføres, kører Spring Security et filter, der er ansvarligt for lagring af sikkerhedskonteksten mellem anmodninger - SecurityContextPersistenceFilter. Konteksten gemmes i henhold til en strategi - HttpSessionSecurityContextRepository som standard - som bruger HTTP-sessionen som lager.

For de strenge create-session = ”stateless” attribut, denne strategi vil blive erstattet med en anden - NullSecurityContextRepository - og ingen session oprettes eller bruges for at bevare konteksten.

4. Samtidig sessionskontrol

Når en bruger, der allerede er godkendt, prøver at godkend igen, applikationen kan håndtere denne begivenhed på en af ​​få måder. Det kan enten ugyldiggøre brugerens aktive session og godkende brugeren igen med en ny session eller tillade, at begge sessioner eksisterer samtidigt.

Det første trin i at muliggøre den samtidige session-kontrol support er at tilføje følgende lytter i web.xml:

  org.springframework.security.web.session.HttpSessionEventPublisher 

Eller definer det som en bønne - som følger:

@Bean public HttpSessionEventPublisher httpSessionEventPublisher () {returner ny HttpSessionEventPublisher (); }

Dette er vigtigt for at sikre, at Spring Security-sessionsregistret er underrettet, når sessionen er ødelagt.

For at aktivere scenariet, der tillader flere samtidige sessioner for den samme bruger elementet skal bruges i XML-konfigurationen:

Eller via Java-konfiguration:

@ Override beskyttet ugyldig konfiguration (HttpSecurity http) kaster undtagelse {http.sessionManagement (). MaximumSessions (2)}

5. Timeout for session

5.1. Håndtering af sessionstimeout

Når sessionen er udløbet, hvis brugeren sender en anmodning med en udløbet session-id, de omdirigeres til en URL, der kan konfigureres via navneområdet:

Tilsvarende, hvis brugeren sender en anmodning med et sessions-id, som ikke er udløbet, men helt ugyldig, de vil også blive omdirigeret til en konfigurerbar URL:

 ... 

Den tilsvarende Java-konfiguration:

http.sessionManagement () .expiredUrl ("/ sessionExpired.html") .invalidSessionUrl ("/ invalidSession.html");

5.2. Konfigurer sessionstimeout med Spring Boot

Vi kan nemt konfigurere Session timeout-værdien på den integrerede server ved hjælp af egenskaber:

server.servlet.session.timeout = 15m

Hvis vi ikke specificerer varighedsenheden, antager Spring, at det er sekunder.

Kort sagt med denne konfiguration udløber sessionen efter 15 minutters inaktivitet. Sessionen efter denne periode betragtes som ugyldig.

Hvis vi konfigurerede vores projekt til at bruge Tomcat, er vi nødt til at huske på, at det kun understøtter minutpræcision til sessionstimeout med mindst et minut. Dette betyder, at hvis vi angiver en timeoutværdi på 170'erne for eksempel vil det resultere i 2 minutters timeout.

Endelig er det vigtigt at nævne, at selvom Spring Session understøtter en lignende egenskab til dette formål (spring.session.timeout), hvis dette ikke er angivet, falder autokonfigurationen tilbage til værdien af ​​den ejendom, vi først nævnte.

6. Undgå brug af URL-parametre til sessionssporing

At eksponere sessionsoplysninger i URL'en er en voksende sikkerhedsrisiko (fra sted 7 i 2007 til sted 2 i 2013 på OWASPs top 10-liste).

Startende med Spring 3.0, URL-omskrivningslogikken, der tilføjede jsessionid til URL'en kan nu deaktiveres ved at indstille disable-url-rewriting = ”true” i navneområde.

Alternativt kan sessionsporingsmekanismen startende med Servlet 3.0 også konfigureres i web.xml:

 COOKIE 

Og programmatisk:

servletContext.setSessionTrackingModes (EnumSet.of (SessionTrackingMode.COOKIE));

Dette vælger, hvor det skal opbevares JSESSIONID - i cookien eller i en URL-parameter.

7. Sessionsfikseringsbeskyttelse med forårssikkerhed

Rammen giver beskyttelse mod typiske Session Fixation-angreb ved at konfigurere, hvad der sker med en eksisterende session, når brugeren forsøger at godkende igen:

 ...

Den tilsvarende Java-konfiguration:

http.sessionManagement () .sessionFixation (). migrateSession ()

Som standard har Spring Security denne beskyttelse aktiveret (“migrateSession“) - ved godkendelse oprettes en ny HTTP-session, den gamle ugyldiggøres og attributterne fra den gamle session kopieres.

Hvis dette ikke er den ønskede adfærd, er to andre muligheder tilgængelige:

  • hvornår "ingen”Er indstillet, annulleres den originale session ikke
  • hvornår "newSession”Er indstillet, oprettes en ren session uden at nogen af ​​attributterne fra den gamle session kopieres

8. Secure Session Cookie

Dernæst diskuterer vi, hvordan vi sikrer vores session cookie.

Vi kan bruge httpKun og sikker flag for at sikre vores session cookie:

  • httpKun: hvis det er sandt, kan browserscript ikke få adgang til cookien
  • sikker: hvis det er sandt, sendes cookien kun via HTTPS-forbindelse

Vi kan indstille disse flag til vores session cookie i web.xml:

 1 sandt sandt 

Denne konfigurationsindstilling er tilgængelig siden Java-servlet 3. Som standard kun http er sandt og sikker er falsk.

Lad os også se på den tilsvarende Java-konfiguration:

offentlig klasse MainWebAppInitializer implementerer WebApplicationInitializer {@Override public void onStartup (ServletContext sc) kaster ServletException {// ... sc.getSessionCookieConfig (). setHttpOnly (true); sc.getSessionCookieConfig (). setSecure (sand); }}

Hvis vi bruger Spring Boot, kan vi indstille disse flag i vores application.properties:

server.servlet.session.cookie.http-only = sand server.servlet.session.cookie.secure = sand

Endelig kan vi også opnå dette manuelt ved hjælp af en Filter:

offentlig klasse SessionFilter implementerer filter {@Override public void doFilter (ServletRequest anmodning, ServletResponse svar, FilterChain kæde) kaster IOException, ServletException {HttpServletRequest req = (HttpServletRequest) anmodning; HttpServletResponse res = (HttpServletResponse) svar; Cookie [] allCookies = req.getCookies (); hvis (allCookies! = null) {Cookiesession = Arrays.stream (allCookies) .filter (x -> x.getName (). er lig med ("JSESSIONID")) .findFirst (). ellerElse (null); hvis (session! = null) {session.setHttpOnly (sand); session.setSecure (sand); res.addCookie (session); }} chain.doFilter (req, res); }}

9. Arbejde med sessionen

9.1. Session Scoped Beans

En bønne kan defineres med session rækkevidde ved blot at bruge @Scope-kommentaren på bønner, der er erklæret i web-Context:

@Component @Scope ("session") offentlig klasse Foo {..}

Eller med XML:

Derefter kan bønnen simpelthen injiceres i en anden bønne:

@Autowired privat Foo theFoo;

Og Spring vil binde den nye bønne til livscyklussen for HTTP-sessionen.

9.2. Injektion af den rå session i en controller

Den rå HTTP-session kan også injiceres direkte i en Controller metode:

@RequestMapping (..) offentlig ugyldighed fooMethod (HttpSession-session) {session.setAttribute (Constants.FOO, ny Foo ()); // ... Foo foo = (Foo) session.getAttribute (Constants.FOO); }

9.3. Opnåelse af den rå session

Den aktuelle HTTP-session kan også opnås programmatisk via rå Servlet API:

ServletRequestAttributter attr = (ServletRequestAttributter) RequestContextHolder.currentRequestAttributter (); HttpSession-session = attr.getRequest (). GetSession (sand); // sand == tillad oprettelse

10. Konklusion

I denne artikel diskuterede vi styring af sessioner med Spring Security. Forårsreferencen indeholder også en meget god FAQ om session management.

Som altid er koden præsenteret i denne artikel tilgængelig på Github. Dette er et Maven-baseret projekt, så det skal være let at importere og køre som det er.