Više ulaznih bodova u proljetnoj sigurnosti

1. Pregled

U ovom ćemo brzom vodiču pogledati kako to učiniti definirati više ulaznih točaka u aplikaciji Spring Security.

To uglavnom podrazumijeva definiranje višestrukih http blokova u XML datoteci za konfiguraciju ili više njih HttpSecurity instancama proširivanjem WebSecurityConfigurerAdapter klasa više puta.

2. Ovisnosti Mavena

Za razvoj trebat će nam sljedeće ovisnosti:

 org.springframework.boot spring-boot-starter-security 2.2.2.RELEASE org.springframework.boot spring-boot-starter-web 2.2.2.RELEASE org.springframework.boot spring-boot-starter-thymeleaf 2.2.2. RELEASE org.springframework.boot spring-boot-starter-test 2.2.2.RELEASE org.springframework.security spring-security-test 5.2.2.RELEASE 

Najnovije verzije spring-boot-starter-security, spring-boot-starter-web, spring-boot-starter-thymeleaf, spring-boot-starter-test, spring-security-test mogu se preuzeti s Maven Central.

3. Više ulaznih bodova

3.1. Više ulaznih bodova s ​​više HTTP elemenata

Definirajmo glavnu konfiguracijsku klasu koja će sadržavati korisnički izvor:

@Configuration @EnableWebSecurity javna klasa MultipleEntryPointsSecurityConfig {@Bean public UserDetailsService userDetailsService () baca izuzetak {InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager (); manager.createUser (User .withUsername ("user") .password (encoder (). encode ("userPass")) .roles ("USER"). build ()); manager.createUser (User .withUsername ("admin") .password (encoder (). encode ("adminPass")) .roles ("ADMIN"). build ()); upravitelj povratka; } @Bean javni koder PasswordEncoder () {vratiti novi BCryptPasswordEncoder (); }}

Pogledajmo sada kako možemo definirati više ulaznih točaka u našoj sigurnosnoj konfiguraciji.

Ovdje ćemo upotrijebiti primjer vođen osnovnom autentifikacijom i dobro ćemo iskoristiti činjenicu da Spring Security podržava definiciju višestrukih HTTP elemenata u našim konfiguracijama.

Kada koristite Java konfiguraciju, način definiranja više sigurnosnih područja je imati više njih @Konfiguracija klase koje proširuju WebSecurityConfigurerAdapter osnovna klasa - svaka sa svojom sigurnosnom konfiguracijom. Te klase mogu biti statične i smještene unutar glavne konfiguracije.

Glavna motivacija za postojanje više ulaznih točaka u jednom programu je ako postoje različiti tipovi korisnika koji mogu pristupiti različitim dijelovima aplikacije.

Definirajmo konfiguraciju s tri ulazne točke, svaka s različitim dozvolama i načinima provjere autentičnosti:

  • jedan za administrativne korisnike koji koriste HTTP osnovnu provjeru autentičnosti
  • jedan za redovne korisnike koji koriste provjeru autentičnosti obrasca
  • i jedan za gostujuće korisnike koji ne zahtijevaju provjeru autentičnosti

Ulazna točka definirana za administrativne korisnike osigurava URL-ove obrasca / admin / ** kako bi se omogućilo samo korisnicima s ulogom ADMINISTIKA i potrebna je HTTP osnovna provjera autentičnosti s ulaznom točkom tipa BasicAuthenticationEntryPoint koji se postavlja pomoću authenticationEntryPoint () metoda:

@Configuration @Order (1) javna statička klasa App1ConfigurationAdapter proširuje WebSecurityConfigurerAdapter {@Override zaštićena void konfiguracija (HttpSecurity http) baca iznimku {http.antMatcher ("/ admin / **") .authorizeRequests (). AnyRequest (). ADMINISTRATOR ") .and (). HttpBasic (). AuthenticationEntryPoint (authenticationEntryPoint ()); } @Bean public AuthenticationEntryPoint authenticationEntryPoint () {BasicAuthenticationEntryPoint entryPoint = novi BasicAuthenticationEntryPoint (); entryPoint.setRealmName ("carstvo administratora"); povratak entryPoint; }}

The @Narudžba napomena za svaku statičku klasu označava redoslijed kojim će se uzeti u obzir da će konfiguracije pronaći onu koja odgovara traženom URL-u. The narudžba vrijednost za svaki razred mora biti jedinstvena.

Grah tipa BasicAuthenticationEntryPoint zahtijeva imovinu pravo ime biti postavljen.

3.2. Više ulaznih bodova, isti HTTP element

Dalje, definirajmo konfiguraciju za URL-ove obrasca /korisnik/** kojima mogu pristupiti redovni korisnici s USER ulogom pomoću provjere autentičnosti obrasca:

@Configuration @Order (2) javna statička klasa App2ConfigurationAdapter proširuje WebSecurityConfigurerAdapter {zaštićena void konfiguracija (HttpSecurity http) baca izuzetak {http.antMatcher ("/ user / **") .authorizeRequests (). AnyRequest (). HasRole ("USER". ) .and () // configLogin configuration .and () .exceptionHandling () .defaultAuthenticationEntryPointFor (loginUrlauthenticationEntryPointWithWarning (), new AntPathRequestMatcher ("/ user / private / **")) .defaultAuthenticationEntryPointFornt ( korisnik / općenito / ** ")); }}

Kao što vidimo, drugi način definiranja ulaznih točaka, pored metode authenticationEntryPoint (), jest i korištenje defaultAuthenticationEntryPointFor () metoda. To može definirati više ulaznih točaka koje se podudaraju s različitim uvjetima na temelju a RequestMatcher objekt.

The RequestMatcher sučelje ima implementacije zasnovane na različitim vrstama uvjeta, poput podudarne staze, vrste medija ili regularnog izraza. U našem primjeru koristili smo AntPathRequestMatch za postavljanje dviju različitih ulaznih točaka za URL-ove obrazaca / user / private / ** i / user / general / **.

Dalje, moramo definirati grah ulaznih točaka u istoj klasi statičke konfiguracije:

@Bean public AuthenticationEntryPoint loginUrlauthenticationEntryPoint () {return new LoginUrlAuthenticationEntryPoint ("/ userLogin"); } @Bean public AuthenticationEntryPoint loginUrlauthenticationEntryPointWithWarning () {return new LoginUrlAuthenticationEntryPoint ("/ userLoginWithWarning"); }

Ovdje je glavno kako postaviti te više ulaznih točaka - ne nužno pojedinosti o implementaciji svake od njih.

U ovom su slučaju ulazne točke obje vrste LoginUrlAuthenticationEntryPointi koristite drugačiji URL stranice za prijavu: / userLogin za jednostavnu stranicu za prijavu i / userLoginWithWarning za stranicu za prijavu koja također prikazuje upozorenje prilikom pokušaja pristupa /korisnik/ privatni URL-ovi.

Ova konfiguracija također će trebati definirati / userLogin i / userLoginWithWarning MVC mapiranja i dvije stranice sa standardnim obrascem za prijavu.

Za provjeru autentičnosti obrasca, vrlo je važno imati na umu da svaki URL potreban za konfiguraciju, poput URL-a za obradu prijave, također mora slijediti /korisnik/** formatirati ili biti na neki drugi način konfiguriran tako da bude dostupan.

Obje gore navedene konfiguracije preusmjerit će na /403 URL ako korisnik bez odgovarajuće uloge pokuša pristupiti zaštićenom URL-u.

Pazite da koristite jedinstvena imena za grah, čak i ako su u različitim statičkim klasama, inače će jedno nadvladati drugo.

3.3. Novi HTTP element, bez ulazne točke

Na kraju, definirajmo treću konfiguraciju za URL-ove obrasca /gost/** koji će omogućiti svim vrstama korisnika, uključujući neautorizirane:

@Configuration @Order (3) javna statička klasa App3ConfigurationAdapter proširuje WebSecurityConfigurerAdapter {zaštićena voidna konfiguracija (HttpSecurity http) baca izuzetak {http.antMatcher ("/ gost / **"). AuthreRequests (). AnyRequest (). AllowAll (); }}

3.4. XML konfiguracija

Pogledajmo ekvivalentnu XML konfiguraciju za tri HttpSecurity slučajevi u prethodnom odjeljku.

Kao što se očekivalo, ovo će sadržavati tri odvojena XML-a blokovi.

Za / admin / ** URL-ovi koje će XML konfiguracija koristiti ulazna točka-ref atribut http-osnovno element:

Ovdje treba napomenuti da ako se koristi XML konfiguracija, uloge moraju biti oblika ULOGA_.

Konfiguracija za /korisnik/** URL-ovi će se morati podijeliti na dva dijela http blokovi u xml-u jer nema izravnog ekvivalenta defaultAuthenticationEntryPointFor () metoda.

Konfiguracija za URL-ove / user / general / ** je:

  // konfiguracija prijavne forme 

Za / user / private / ** URL-ove možemo definirati sličnu konfiguraciju:

  // konfiguracija prijavne forme 

Za /gost/** URL-ovi koje ćemo imati http element:

Ovdje je također važno da barem jedan XML blok mora odgovarati uzorku / **.

4. Pristup zaštićenim URL-ovima

4.1. MVC konfiguracija

Stvorimo mapiranja zahtjeva koji se podudaraju s uzorcima URL-a koje smo osigurali:

@Controller javna klasa PagesController {@GetMapping ("/ admin / myAdminPage") javni niz getAdminPage () {return "multipleHttpElems / myAdminPage"; } @GetMapping ("/ user / general / myUserPage") javni niz getUserPage () {return "multipleHttpElems / myUserPage"; } @GetMapping ("/ user / private / myPrivateUserPage") javni niz getPrivateUserPage () {return "multipleHttpElems / myPrivateUserPage"; } @GetMapping ("/ guest / myGuestPage") javni niz getGuestPage () {return "multipleHttpElems / myGuestPage"; } @GetMapping ("/ multipleHttpLinks") javni niz getMultipleHttpLinksPage () {return "multipleHttpElems / multipleHttpLinks"; }}

The / multipleHttpLinks mapiranje će vratiti jednostavnu HTML stranicu s vezama na zaštićene URL-ove:

Administratorska stranica Korisnička stranica Privatna korisnička stranica Stranica za goste

Svaka od HTML stranica koje odgovaraju zaštićenim URL-ima imat će jednostavan tekst i povratnu vezu:

Dobrodošao admin! Povratak na linkove

4.2. Inicijalizacija aplikacije

Izvest ćemo naš primjer kao aplikaciju Spring Boot, pa definirajmo klasu glavnom metodom:

@SpringBootApplication javna klasa MultipleEntryPointsApplication {javna statička void glavna (String [] args) {SpringApplication.run (MultipleEntryPointsApplication.class, args); }}

Ako želimo koristiti XML konfiguraciju, trebamo dodati i @ImportResource ({“classpath *: spring-security-multiple-entry.xml”}) napomena za našu glavnu klasu.

4.3. Testiranje sigurnosne konfiguracije

Postavimo testnu klasu JUnit koju možemo koristiti za testiranje naših zaštićenih URL-ova:

@RunWith (SpringRunner.class) @WebAppConfiguration @SpringBootTest (classes = MultipleEntryPointsApplication.class) javna klasa MultipleEntryPointsTest {@Autowired private WebApplicationContext wac; @Autowired private FilterChainProxy springSecurityFilterChain; privatni MockMvc mockMvc; @Prije javne void setup () {this.mockMvc = MockMvcBuilders.webAppContextSetup (this.wac) .addFilter (springSecurityFilterChain) .build (); }}

Dalje, testirajmo URL-ove pomoću admin korisnik.

Kada se traži / admin / adminPage URL bez HTTP osnovne provjere autentičnosti, trebali bismo očekivati ​​primanje neovlaštenog statusnog koda, a nakon dodavanja provjere identiteta statusni bi kôd trebao biti 200 OK.

Ako pokušavate pristupiti / user / userPage URL s administratorskim korisnikom, trebali bismo dobiti status 302 Zabranjeno:

@Test public void whenTestAdminCredentials_thenOk () baca iznimku {mockMvc.perform (get ("/ admin / myAdminPage")). AndExpect (status (). IsUnauthorized ()); mockMvc.perform (get ("/ admin / myAdminPage") .with (httpBasic ("admin", "adminPass"))). andExpect (status (). isOk ()); mockMvc.perform (get ("/ user / myUserPage") .with (user ("admin"). password ("adminPass"). role ("ADMIN"))) .andExpect (status (). isForbidden ()); }

Stvorimo sličan test koristeći uobičajene vjerodajnice za pristup URL-ovima:

@Test public void whenTestUserCredentials_thenOk () baca iznimku {mockMvc.perform (get ("/ user / general / myUserPage")). AndExpect (status (). IsFound ()); mockMvc.perform (get ("/ user / general / myUserPage") .with (user ("user"). password ("userPass"). role ("USER"))) .andExpect (status (). isOk () ); mockMvc.perform (get ("/ admin / myAdminPage") .with (user ("user"). password ("userPass"). role ("USER"))) .andExpect (status (). isForbidden ()); }

U drugom testu možemo vidjeti da će nedostatak autentifikacije obrasca rezultirati statusom 302 Pronađeno umjesto Neovlašteno, jer će Spring Security preusmjeriti na obrazac za prijavu.

Na kraju, kreirajmo test u kojem pristupamo / gost / gostPage URL će sve tri vrste provjere autentičnosti i potvrditi da smo dobili status 200 OK:

@Test javna praznina givenAnyUser_whenGetGuestPage_thenOk () baca izuzetak {mockMvc.perform (get ("/ guest / myGuestPage")). AndExpect (status (). IsOk ()); mockMvc.perform (get ("/ guest / myGuestPage") .with (user ("user"). password ("userPass"). role ("USER"))) .andExpect (status (). isOk ()); mockMvc.perform (get ("/ guest / myGuestPage") .with (httpBasic ("admin", "adminPass"))) .andExpect (status (). isOk ()); }

5. Zaključak

U ovom smo uputstvu pokazali kako konfigurirati više ulaznih točaka kada koristite Spring Security.

Kompletni izvorni kod za primjere možete pronaći na GitHubu. Da biste pokrenuli aplikaciju, uklonite komentar iz MultipleEntryPointsApplicationpočetna klasa oznaka u pom.xml i pokrenite naredbu mvn spring-boot: trčanje, zatim pristupa / multipleHttpLinks URL.

Imajte na umu da se nije moguće odjaviti kada se koristi HTTP osnovna provjera autentičnosti, pa ćete morati zatvoriti i ponovo otvoriti preglednik da biste uklonili ovu provjeru autentičnosti.

Da biste pokrenuli test JUnit, upotrijebite definirani Maven profil ulazne bodove sa sljedećom naredbom:

mvn čista instalacija -PentryPoints


$config[zx-auto] not found$config[zx-overlay] not found