Kontrolirajte sesiju proljetnim osiguranjem

1. Pregled

U ovom ćemo članku ilustrirati kako Spring Security omogućuje nam kontrolu nad našim HTTP sesijama.

Ova se kontrola kreće od vremenskog ograničenja sesije do omogućavanja istodobnih sesija i ostalih naprednih sigurnosnih konfiguracija.

2. Kada se stvara sjednica?

Možemo točno kontrolirati kada će se naša sesija stvoriti i kako će Spring Security s njom komunicirati:

  • stalno- sesija će se uvijek stvoriti ako već ne postoji
  • ako je potrebno- sesija će se stvoriti samo ako je potrebno (zadano)
  • nikada- okvir nikada neće stvoriti samu sesiju, ali će je koristiti ako već postoji
  • apatrid- Spring Security neće stvoriti niti koristiti sesiju
...

Java konfiguracija:

@Override zaštićena void konfiguracija (HttpSecurity http) baca izuzetak {http.sessionManagement () .sessionCreationPolicy (SessionCreationPolicy.IF_REQUIRED)}

Vrlo je važno to razumjeti ova konfiguracija kontrolira samo ono što čini Spring Security - ne cijelu aplikaciju. Spring Security možda neće stvoriti sesiju ako je naložimo da ne radi, ali naša aplikacija može!

Prema zadanim postavkama, Spring Security stvorit će sesiju kada je treba - ovo je "ako je potrebno“.

Za aplikacija bez državljanstva, „nikada”Opcija osigurat će da sama Spring Security neće stvoriti nijednu sesiju; međutim, ako je aplikacija stvori, tada će je iskoristiti Spring Security.

Konačno, najstroža opcija za stvaranje sesija - “apatrid" - je jamče da aplikacija uopće neće stvoriti nijednu sesiju.

Ovo je uvedeno u proljeće 3.1 i učinkovito će preskočiti dijelove lanca filtara Spring Security - uglavnom dijelove povezane sa sesijom, kao što su HttpSessionSecurityContextRepository, SessionManagementFilter, RequestCacheFilter.

Ovi strožiji mehanizmi kontrole imaju izravnu implikaciju da kolačići se ne koriste i tako svaki zahtjev treba ponovno potvrditi. Ova arhitektura bez državljanstva dobro se poigrava s REST API-ima i njihovim ograničenjima apatridnosti. Također dobro rade s mehanizmima provjere autentičnosti, kao što su osnovna i digest provjera autentičnosti.

3. Ispod haube

Prije izvođenja postupka provjere autentičnosti, Spring Security pokrenut će filter odgovoran za pohranu sigurnosnog konteksta između zahtjeva - SecurityContextPersistenceFilter. Kontekst će biti pohranjen prema strategiji - HttpSessionSecurityContextRepository prema zadanim postavkama - koja koristi HTTP sesiju kao pohranu.

Za stroge create-session = "bez državljanstva" atribut, ova će strategija biti zamijenjena drugom - NullSecurityContextRepository - i nijedna sesija neće biti stvorena ili korištena zadržati kontekst.

4. Kontrola istodobne sesije

Kada korisnik koji je već ovjeren pokušava ponovno ovjeriti, aplikacija se može nositi s tim događajem na jedan od nekoliko načina. Može onesposobiti aktivnu sesiju korisnika i ponovno ovjeriti korisnika novom sesijom ili dopustiti da obje sesije istodobno postoje.

Prvi korak u omogućavanju istodobnog kontrola sjednice podrška je dodavanje sljedećeg slušatelja u web.xml:

  org.springframework.security.web.session.HttpSessionEventPublisher 

Ili ga definirajte kao grah - kako slijedi:

@Bean public HttpSessionEventPublisher httpSessionEventPublisher () {return new HttpSessionEventPublisher (); }

To je neophodno kako biste bili sigurni da je registar sesije Spring Security obaviješten kad je sesija uništena.

Da biste omogućili scenarij koji omogućava više istodobnih sesija za istog korisnika, element treba koristiti u XML konfiguraciji:

Ili putem Java konfiguracije:

@Override zaštićena void konfiguracija (HttpSecurity http) baca iznimku {http.sessionManagement (). MaximumSessions (2)}

5. Istek sesije

5.1. Rukovanje vremenskim ograničenjem sesije

Nakon isteka sesije, ako korisnik pošalje zahtjev s istekao ID sesije, oni će biti preusmjereni na URL koji se može konfigurirati putem prostora imena:

Slično tome, ako korisnik pošalje zahtjev s ID-om sesije koji nije istekao, već u cijelosti nevaljano, oni će također biti preusmjereni na podesivi URL:

 ... 

Odgovarajuća Java konfiguracija:

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

5.2. Konfigurirajte vremensko ograničenje sesije pomoću Spring Boot

Vrijednost vremenskog ograničenja sesije ugrađenog poslužitelja možemo lako konfigurirati pomoću svojstava:

server.servlet.session.timeout = 15m

Ako ne odredimo jedinicu trajanja, Spring će pretpostaviti da su to sekunde.

Ukratko, s ovom konfiguracijom, nakon 15 minuta neaktivnosti, sesija istječe. Sjednica nakon tog vremenskog razdoblja smatra se nevaljanom.

Ako smo svoj projekt konfigurirali da koristi Tomcat, moramo imati na umu da podržava samo preciznost minuta za vremensko ograničenje sesije, s najmanje jednom minutom. To znači da ako odredimo vrijednost vremenskog ograničenja od 170-te na primjer, rezultirat će 2-minutnim vremenskim ograničenjem.

Na kraju, važno je spomenuti da iako Spring Session podržava slično svojstvo u tu svrhu (proljeće.sesija.tajmout), ako to nije navedeno, tada će se automatska konfiguracija vratiti na vrijednost svojstva koje smo prvo spomenuli.

6. Spriječite upotrebu parametara URL-a za praćenje sesija

Izlaganje podataka o sesiji u URL-u rastući je sigurnosni rizik (od 7. mjesta 2007. do 2. mjesta 2013. na OWASP-ovih 10 najboljih popisa).

Počevši od Spring 3.0, logika prepisivanja URL-a koja bi dodala jsessionid na URL sada se može onemogućiti postavljanjem disable-url-rewriting = "istina" u prostor imena.

Alternativno, počevši od Servlet 3.0, mehanizam za praćenje sesija također se može konfigurirati u web.xml:

 KOLAČIĆ 

I programski:

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

Ovim se bira gdje će se JSESSIONID - u kolačiću ili u parametru URL-a.

7. Zaštita fiksacije sesije proljetnom sigurnošću

Okvir nudi zaštitu od tipičnih napada fiksiranja sesije konfiguriranjem onoga što se događa postojećoj sesiji kada korisnik ponovno pokuša provjeriti autentičnost:

 ...

Odgovarajuća Java konfiguracija:

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

Prema zadanim postavkama Spring Security ima omogućenu ovu zaštitu („migrateSession“) - prilikom provjere autentičnosti stvara se nova HTTP sesija, stara se poništava i kopiraju se atributi iz stare sesije.

Ako ovo nije željeno ponašanje, dostupne su dvije druge mogućnosti:

  • kada "nijedna”Postavljeno je, izvorna sesija neće biti poništena
  • kada "newSession"Postavljeno je, stvorit će se čista sesija bez kopiranja bilo kojeg atributa iz stare sesije

8. Kolačić sigurne sesije

Dalje ćemo razgovarati o tome kako osigurati kolačić sesije.

Možemo koristiti httpSamo i siguran zastavice za zaštitu našeg kolačića sesije:

  • samo http: ako je tačno, skripta preglednika neće moći pristupiti kolačiću
  • siguran: ako je tačno, kolačić će biti poslan samo putem HTTPS veze

Te zastavice možemo postaviti za kolačić naše sesije u web.xml:

 1 istina istina 

Ova je opcija konfiguracije dostupna od Java servleta 3. Prema zadanim postavkama, samo http je istina i siguran je lažno.

Pogledajmo i odgovarajuću Java konfiguraciju:

javna klasa MainWebAppInitializer implementira WebApplicationInitializer {@Override public void onStartup (ServletContext sc) baca ServletException {// ... sc.getSessionCookieConfig (). setHttpOnly (true); sc.getSessionCookieConfig (). setSecure (true); }}

Ako koristimo Spring Boot, ove zastavice možemo postaviti u naš primjena.svojstva:

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

Napokon, to možemo postići i ručno pomoću a filtar:

javna klasa SessionFilter implementira Filter {@Override public void doFilter (ServletRequest zahtjev, ServletResponse odgovor, FilterChain lanac) baca IOException, ServletException {HttpServletRequest zahtjev (HttpServletRequest) zahtjev; HttpServletResponse res = (HttpServletResponse) odgovor; Kolačić [] allCookies = req.getCookies (); if (allCookies! = null) {Cookie session = Arrays.stream (allCookies) .filter (x -> x.getName (). equals ("JSESSIONID")) .findFirst (). orElse (null); if (session! = null) {session.setHttpOnly (true); session.setSecure (true); res.addCookie (sesija); }} chain.doFilter (req, res); }}

9. Rad sa sjednicom

9.1. Grah s opsegom zasjedanja

Grah se može definirati s sjednica opseg jednostavnim korištenjem bilješke @Scope na grahu deklariranom u web-kontekstu:

@Component @Scope ("session") javna klasa Foo {..}

Ili s XML-om:

Zatim se grah može jednostavno ubrizgati u drugi grah:

@Autowired private Foo theFoo;

A Spring će vezati novi grah za životni ciklus HTTP sesije.

9.2. Ubrizgavanje sirove sesije u kontroler

Sirova HTTP sesija također se može ubrizgati izravno u Kontroler metoda:

@RequestMapping (..) public void fooMethod (HttpSession session) {session.setAttribute (Constants.FOO, new Foo ()); // ... Foo foo = (Foo) session.getAttribute (Constants.FOO); }

9.3. Dobivanje sirove sesije

Trenutna HTTP sesija također se može programski dobiti putem API sirovog Servleta:

ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes (); HttpSession sesija = attr.getRequest (). GetSession (true); // true == dopustiti stvaranje

10. Zaključak

U ovom smo članku razgovarali o upravljanju sesijama s Spring Security. Također, Spring Reference sadrži vrlo dobar FAQ o upravljanju sjednicama.

Kao i uvijek, kôd predstavljen u ovom članku dostupan je na Githubu. Ovo je projekt zasnovan na Mavenu, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.