Tavaszi felhő - Biztonsági szolgáltatások

1. Áttekintés

Az előző cikkben, a Spring Cloud - Bootstrapping-ben egy alapszintet építettünk Tavaszi felhő Alkalmazás. Ez a cikk bemutatja, hogyan lehet rögzíteni.

Természetesen használni fogjuk Tavaszi biztonság a munkamenetek használatával Tavaszi ülés és Redis. Ez a módszer egyszerűen beállítható és könnyen kiterjeszthető számos üzleti forgatókönyvre. Ha nem ismeri Tavaszi ülés, nézze meg ezt a cikket.

A munkamenetek megosztása lehetővé teszi számunkra a felhasználók naplózását az átjáró szolgáltatásunkban, és a hitelesítés terjesztését a rendszer bármely más szolgáltatásába.

Ha nem ismeri Redis vagyTavaszi biztonság, célszerű ezen a ponton gyorsan áttekinteni ezeket a témákat. Bár a cikk nagy része készen áll a másolás-beillesztésre egy alkalmazás számára, semmi sem helyettesíti annak megértését, hogy mi történik a motorháztető alatt.

Bevezetés a Redis olvassa el ezt az oktatóanyagot. Bevezetés a Tavaszi biztonság olvassa el a spring-security-login, a role-and-privilege-for-tavaszi-security-register és a spring-security-session témákat. A teljes megértéshez Spring Security, vessen egy pillantást a Learn-Spring-Security-the-Master-osztályra.

2. Maven Setup

Kezdjük azzal, hogy hozzáadjuk a spring-boot-starter-security függőséget a rendszer minden moduljához:

 org.springframework.boot spring-boot-starter-security 

Mert használjuk Tavaszi függőségkezelés, amelynek verzióit elhagyhatjuk rugós-bakancs-indító függőségek.

Második lépésként módosítsuk a pom.xml az egyes alkalmazások tavaszi munkamenet, tavaszi indítás-indító-adatok-redis függőségekkel:

 org.springframework.session tavaszi ülés org.springframework.boot spring-boot-starter-data-redis 

Csak négy alkalmazásunk kapcsolódik be Tavaszi ülés: felfedezés, átjáró, könyv-szolgáltatás, és minősítés-szolgáltatás.

Ezután adjon hozzá egy munkamenet konfigurációs osztályt mindhárom szolgáltatáshoz ugyanabban a könyvtárban, mint a fő alkalmazásfájl:

@EnableRedisHttpSession public class SessionConfig kiterjeszti az AbstractHttpSessionApplicationInitializer {}

Végül adja hozzá ezeket a tulajdonságokat a háromhoz * .tulajdonságok fájlok a git-tárunkban:

spring.redis.host = localhost spring.redis.port = 6379

Most térjünk át a szolgáltatásspecifikus konfigurációra.

3. Biztonsági Config szolgáltatás

A konfigurációs szolgáltatás érzékeny információkat tartalmaz, amelyek gyakran kapcsolódnak az adatbázis-kapcsolatokhoz és az API-kulcsokhoz. Nem veszélyeztethetjük ezeket az információkat, ezért merüljünk el közvetlenül, és biztosítsuk ezt a szolgáltatást.

Adjunk hozzá biztonsági tulajdonságokat a alkalmazás.tulajdonságok fájl src / main / resources konfigurációs szolgáltatás:

eureka.client.serviceUrl.defaultZone = // discUser: [e-mail védett]: 8082 / eureka / security.user.name = configUser security.user.password = configPassword security.user.role = SYSTEM

Ez beállítja szolgáltatásunkat, hogy felfedezéssel bejelentkezzen. Ezen felül konfiguráljuk a biztonságunkat a alkalmazás.tulajdonságok fájl.

Konfiguráljuk most a felfedezési szolgáltatásunkat.

4. A Discovery szolgáltatás biztosítása

Felfedezési szolgáltatásunk bizalmas információkat tárol az alkalmazás összes szolgáltatásának helyéről. Ezen szolgáltatások új példányait is regisztrálja.

Ha a rosszindulatú ügyfelek hozzáférnek, megtanulják a rendszerünk összes szolgáltatásának hálózati helyét, és regisztrálni tudják saját rosszindulatú szolgáltatásaikat az alkalmazásunkba. Kritikus, hogy a felfedezési szolgáltatás biztonságban legyen.

4.1. Biztonsági konfiguráció

Vegyünk fel egy biztonsági szűrőt a többi szolgáltatás által használt végpontok védelmére:

@Configuration @EnableWebSecurity @Order (1) A SecurityConfig nyilvános osztály kiterjeszti a WebSecurityConfigurerAdapter {@Autowired public void configureGlobal (AuthenticationManagerBuilder auth) {auth.inMemoryAuthentication (). WithUser ("discUser "assword (password) ); } @Orride védett void konfigurálás (HttpSecurity http) {http.sessionManagement () .sessionCreationPolicy (SessionCreationPolicy.ALWAYS) .és (). RequestMatchers (). AntMatchers ("/ eureka / **") .and (). AuthorizeRequests () .antMatchers ("/ eureka / **") .hasRole ("SYSTEM"). anyRequest (). denyAll (). és () .httpBasic (). és (). csrf (). disable (); }}

Ez szolgáltatásunkat egy „RENDSZER’Felhasználó. Ez egy alap Tavaszi biztonság konfiguráció néhány csavarral. Vessünk egy pillantást ezekre a fordulatokra:

  • @Rendelés (1) - meséli Tavaszi kösse be először ezt a biztonsági szűrőt, hogy megkíséreljék mások előtt
  • .sessionCreationPolicy - meséli Tavaszi hogy mindig hozzon létre egy munkamenetet, amikor a felhasználó bejelentkezik erre a szűrőre
  • .requestMatchers - korlátozza, hogy a szűrő milyen végpontokra vonatkozik

Az imént beállított biztonsági szűrő egy elszigetelt hitelesítési környezetet konfigurál, amely csak a felfedezési szolgáltatásra vonatkozik.

4.2. Az Eureka Irányítópult rögzítése

Mivel a felfedező alkalmazásunknak van egy szép felhasználói felülete a jelenleg regisztrált szolgáltatások megtekintésére, tegyük ki, hogy egy második biztonsági szűrőt használva kösse össze ezt az alkalmazás többi részének hitelesítésével. Ne feledje, hogy nem @Rendelés() a címke azt jelenti, hogy ez az utolsó értékelendő biztonsági szűrő:

Az @Configuration nyilvános statikus osztálya Az AdminSecurityConfig kiterjeszti a WebSecurityConfigurerAdapter {@Orride védett void configure (HttpSecurity http) {http.sessionManagement (). SessionCreationPolicy (SessionCreationPolicy.NEVER) .and (). HttpBatchic (Author) disable. HttpMethod.GET, "/").hasRole("ADMIN") .antMatchers ("/ info", "/ health"). Hitelesített (). AnyRequest () .denyAll (). És (). Csrf (). Letiltás (); }}

Adja hozzá ezt a konfigurációs osztályt a SecurityConfig osztály. Ez létrehoz egy második biztonsági szűrőt, amely ellenőrzi a felhasználói felületünkhöz való hozzáférést. Ez a szűrő néhány szokatlan tulajdonsággal rendelkezik, nézzük meg ezeket:

  • httpBasic (). disable () - utasítja a tavaszi biztonságot, hogy tiltsa le a szűrő összes hitelesítési eljárását
  • sessionCreationPolicy - ezt beállítottuk SOHA annak jelzéséhez, hogy a felhasználónak már hitelesítenie kell magát, mielőtt hozzáférne a szűrővel védett erőforrásokhoz

Ez a szűrő soha nem állít be felhasználói munkamenetet, és erre támaszkodik Redis megosztott biztonsági környezet feltöltésére. Mint ilyen, egy másik szolgáltatástól, az átjárótól függ a hitelesítés.

4.3. Hitelesítés a Config szolgáltatással

A felfedezési projektben csatoljunk két tulajdonságot a bootstrap.tulajdonságok az src / main / resources fájlban:

spring.cloud.config.username = configUser spring.cloud.config.password = configPassword

Ezek a tulajdonságok lehetővé teszik a felfedező szolgáltatás hitelesítését a konfigurációs szolgáltatással indításkor.

Frissítsük a felfedezés.tulajdonságok a Git-tárunkban

eureka.client.serviceUrl.defaultZone = // discUser: [e-mail védett]: 8082 / eureka / eureka.client.register-with-eureka = false eureka.client.fetch-register = false

Felvettük az alapvető hitelesítési adatokat felfedezés szolgáltatás, amely lehetővé teszi számára a kommunikációt a konfig szolgáltatás. Ezenkívül konfiguráljuk Eureka hogy önálló módban fusson azzal, hogy megmondja szolgáltatásunknak, hogy ne regisztráljon önmagában.

Vegyük át a fájlt a git adattár. Ellenkező esetben a változásokat nem észlelik.

5. Az átjáró szolgáltatás biztonsága

Átjáró szolgáltatásunk az egyetlen olyan alkalmazásunk, amelyet a világ elé akarunk tárni. Mint ilyen, biztonságra lesz szüksége annak biztosításához, hogy csak hitelesített felhasználók férhessenek hozzá a bizalmas információkhoz.

5.1. Biztonsági konfiguráció

Hozzunk létre egy SecurityConfig osztály, mint a felfedező szolgáltatásunk, és felülírja a módszereket ezzel a tartalommal:

@Autowired public void configureGlobal (AuthenticationManagerBuilder auth) {auth.inMemoryAuthentication (). WithUser ("user"). Password ("password") .roles ("USER"). And (). WithUser ("admin"). Password ( "admin") .roles ("ADMIN"); } @Orride védett void konfigurálás (HttpSecurity http) {http.authorizeRequests (). AntMatchers ("/ book-service / books") .permitAll (). AntMatchers ("/ eureka / **"). HasRole ("ADMIN") .anyRequest (). hitelesített (). és (). formLogin (). és () .logout (). allowAll (). logoutSuccessUrl ("/ book-service / books") .permitAll (). és (). csrf () .kikapcsolható (); }

Ez a konfiguráció elég egyszerű. Kijelentünk egy biztonsági szűrőt űrlap bejelentkezéssel, amely számos végpontot biztosít.

Az / eureka / ** biztonságának célja, hogy megvédje azokat a statikus erőforrásokat, amelyeket az átjáró szolgáltatásunkból az Eureka állapotoldal. Ha a cikkel együtt építi a projektet, másolja a erőforrás / statikus mappát a Github átjáró projektjétől a projektjéhez.

Most módosítjuk a @EnableRedisHttpSession annotáció a config osztályunkon:

@EnableRedisHttpSession (redisFlushMode = RedisFlushMode.IMMEDIATE)

Az öblítési módot azonnal beállítottuk, hogy a munkamenetben bekövetkező változások azonnal fennmaradjanak. Ez segít előkészíteni a hitelesítési tokent az átirányításhoz.

Végül tegyünk hozzá egy ZuulFilter amely bejelentkezés után továbbítja hitelesítési tokenünket:

A @Component public class SessionSavingZuulPreFilter kiterjeszti a ZuulFilter {@Autowired private SessionRepository adattárat; @Orride public boolean shouldFilter () {return true; } @Orride public Object run () {RequestContext context = RequestContext.getCurrentContext (); HttpSession httpSession = context.getRequest (). GetSession (); Munkamenet = repository.getSession (httpSession.getId ()); context.addZuulRequestHeader ("Cookie", "SESSION =" + httpSession.getId ()); return null; } @Orride public String filterType () {return "pre"; } @Orride public int filterOrder () {return 0; }}

Ez a szűrő megragadja a kérést, amikor bejelentkezés után átirányítja, és a munkamenet kulcsát cookie-ként adja hozzá a fejléchez. Ez bejelentkezés után továbbítja a hitelesítést bármely háttérszolgáltatáshoz.

5.2. Hitelesítés a Config és a Discovery Service szolgáltatással

Adjuk hozzá a következő hitelesítési tulajdonságokat a bootstrap.tulajdonságok fájl src / main / resources az átjáró szolgáltatása:

spring.cloud.config.username = configUser spring.cloud.config.password = configPassword eureka.client.serviceUrl.defaultZone = // discUser: [e-mail védett]: 8082 / eureka /

Ezután frissítsük a frissítéseket átjáró.tulajdonságok a Git-tárunkban

management.security.sessions = mindig zuul.routes.book-service.path = / book-service / ** zuul.routes.book-service.sensitive-headers = Set-Cookie, Engedélyezés hystrix.command.book-service.execution .isolation.thread .timeoutInMilliseconds = 600000 zuul.routes.rating-service.path = / rating-service / ** zuul.routes.rating-service.sensitive-headers = Set-Cookie, Authorization hystrix.command.rating-service. execut.isolation.thread .timeoutInMilliseconds = 600000 zuul.routes.discovery.path = / discovery / ** zuul.routes.discovery.sensitive-headers = Set-Cookie, Engedélyezés zuul.routes.discovery.url = // localhost: 8082 hystrix.command.discovery.execution.isolation.thread .timeoutInMilliseconds = 600000

Felvettük a munkamenetek kezelését, hogy mindig munkameneteket hozzunk létre, mert csak egy biztonsági szűrőnk van, amelyet beállíthatunk a tulajdonságfájlban. Ezután hozzáadjuk a sajátunkat Redis gazdagép és szerver tulajdonságai.

Ezenkívül hozzáadtunk egy útvonalat, amely átirányítja a kéréseket a felfedezési szolgáltatásunkhoz. Mivel egy önálló felfedező szolgáltatás nem fog regisztrálni önmagában, meg kell keresnünk a szolgáltatást egy URL-sémával.

Eltávolíthatjuk a serviceUrl.defaultZone ingatlan a átjáró.tulajdonságok fájlt a konfigurációs git-tárunkban. Ez az érték megismétlődik a bootstrap fájl.

Vezessük át a fájlt a Git adattárba, különben a változásokat nem észleljük.

6. A könyvszolgáltatás biztosítása

A könyvszolgáltató szerver érzékeny információkat tárol, amelyeket különféle felhasználók irányítanak. Ezt a szolgáltatást biztosítani kell, hogy megakadályozzuk a védett információk szivárgását a rendszerünkben.

6.1. Biztonsági konfiguráció

Könyvszolgáltatásunk biztosítása érdekében átmásoljuk a dokumentumot SecurityConfig osztályt az átjárótól, és írja felül a módszert ezzel a tartalommal:

@Orride protected void configure (HttpSecurity http) {http.httpBasic (). Disable (). AuthorizeRequests () .antMatchers ("/ books"). AllowAll () .antMatchers ("/ books / *"). HasAnyRole ("USER "," ADMIN ") .hitelesített (). És (). Csrf (). Disable (); }

6.2. Tulajdonságok

Adja hozzá ezeket a tulajdonságokat a bootstrap.tulajdonságok fájl src / main / resources könyvszolgáltatás:

spring.cloud.config.username = configUser spring.cloud.config.password = configPassword eureka.client.serviceUrl.defaultZone = // discUser: [e-mail védett]: 8082 / eureka /

Adjunk hozzá tulajdonságokat a sajátunkhoz könyv-szolgáltatás.tulajdonságok fájl a git-tárunkban:

management.biztonság.session = soha

Eltávolíthatjuk a serviceUrl.defaultZone ingatlan a könyv-szolgáltatás.tulajdonságok fájlt a konfigurációs git-tárunkban. Ez az érték megismétlődik a bootstrap fájl.

Ne felejtse el végrehajtani ezeket a változásokat, hogy a könyvszolgáltatás átvegye őket.

7. Biztonsági besorolási szolgáltatás

A minősítési szolgáltatást is biztosítani kell.

7.1. Biztonsági konfiguráció

Minősítési szolgáltatásunk biztosítása érdekében átmásoljuk a SecurityConfig osztályt az átjárótól, és írja felül a módszert ezzel a tartalommal:

@Orride protected void configure (HttpSecurity http) {http.httpBasic (). Disable (). AuthorizeRequests () .antMatchers ("/ rating"). HasRole ("USER") .antMatchers ("/ rating / all"). HasAnyRole ("USER", "ADMIN"). AnyRequest () .hitelesített (). És (). Csrf (). Disable (); }

Törölhetjük a configureGlobal () módszer a átjáró szolgáltatás.

7.2. Tulajdonságok

Adja hozzá ezeket a tulajdonságokat a bootstrap.tulajdonságok fájl src / main / resources minősítési szolgáltatás:

spring.cloud.config.username = configUser spring.cloud.config.password = configPassword eureka.client.serviceUrl.defaultZone = // discUser: [e-mail védett]: 8082 / eureka /

Vegyük fel tulajdonságokat a minősítési szolgáltatásunkba.tulajdonságok fájl a git-tárunkban:

menedzsment.biztonság.szakok = soha

Eltávolíthatjuk a serviceUrl.defaultZone tulajdonság a minősítési szolgáltatásból.tulajdonságok fájlt a konfigurációs git-tárunkban. Ez az érték megismétlődik a bootstrap fájl.

Ne felejtse el végrehajtani ezeket a változásokat, hogy az értékelési szolgáltatás felvegye őket.

8. Futás és tesztelés

Rajt Redis és az alkalmazás összes szolgáltatása: konfig, felfedezés, átjáró, könyves szolgáltatás, és minősítés-szolgáltatás. Most teszteljünk!

Először hozzunk létre egy teszt osztályt a mi átjáró projektet és hozzon létre egy módszert a tesztünkhöz:

public class GatewayApplicationLiveTest {@Test public void testAccess () {...}}

Ezután állítsuk be tesztünket, és ellenőrizzük, hogy hozzáférhetünk-e védtelenünkhöz / book-service / books erőforrás hozzáadásával ezt a kódrészletet a vizsgálati módszerünkbe:

TestRestTemplate testRestTemplate = új TestRestTemplate (); Karakterlánc tesztUrl = "// localhost: 8080"; ResponseEntity response = testRestTemplate .getForEntity (testUrl + "/ book-service / books", String.class); Assert.assertEquals (HttpStatus.OK, response.getStatusCode ()); Assert.assertNotNull (response.getBody ());

Futtassa ezt a tesztet, és ellenőrizze az eredményeket. Ha hibákat látunk, erősítse meg, hogy az egész alkalmazás sikeresen elindult, és hogy a konfigurációkat a konfigurációs git-tárunkból töltötték be.

Most teszteljük, hogy felhasználóinkat átirányítják-e a bejelentkezéshez, amikor egy védett erőforrást nem hitelesített felhasználóként látogatnak meg, ehhez a kódot a tesztelési módszer végéhez csatolva:

response = testRestTemplate .getForEntity (testUrl + "/ book-service / books / 1", String.osztály); Assert.assertEquals (HttpStatus.FOUND, response.getStatusCode ()); Assert.assertEquals ("// localhost: 8080 / login", response.getHeaders () .get ("Hely"). Get (0));

Futtassa újra a tesztet, és erősítse meg, hogy sikeres volt.

Ezután jelentkezzünk be, majd a munkamenetünk segítségével érjük el a felhasználó által védett eredményt:

MultiValueMap forma = új LinkedMultiValueMap (); form.add ("felhasználónév", "felhasználó"); form.add ("jelszó", "jelszó"); response = testRestTemplate .postForEntity (testUrl + "/ login", form, String.class); 

most vonjuk ki a munkamenetet a cookie-ból, és továbbítsuk a következő kérésre:

String sessionCookie = response.getHeaders (). Get ("Set-Cookie") .get (0) .split (";") [0]; HttpHeaders fejlécek = new HttpHeaders (); fejlécek.add ("Cookie", sessionCookie); HttpEntity httpEntity = új HttpEntity (fejlécek); 

és kérje a védett erőforrást:

válasz = testRestTemplate.exchange (testUrl + "/ book-service / books / 1", HttpMethod.GET, httpEntity, String.class); Assert.assertEquals (HttpStatus.OK, response.getStatusCode ()); Assert.assertNotNull (response.getBody ());

Futtassa újra a tesztet az eredmények megerősítéséhez.

Most próbáljuk meg elérni az adminisztrációs részt ugyanazzal a munkamenettel:

válasz = testRestTemplate.exchange (testUrl + "/ rating-service / rating / all", HttpMethod.GET, httpEntity, String.class); Assert.assertEquals (HttpStatus.FORBIDDEN, response.getStatusCode ());

Futtassa újra a tesztet, és amint az várható volt, korlátozva vagyunk arra, hogy egyszerű adminisztrátorként hozzáférjünk az adminisztrációs területekhez.

A következő teszt ellenőrzi, hogy bejelentkezhetünk-e rendszergazdaként és hozzáférhetünk az adminisztrátor által védett erőforráshoz:

forma.tiszta (); form.add ("felhasználónév", "admin"); form.add ("jelszó", "admin"); response = testRestTemplate .postForEntity (testUrl + "/ login", form, String.class); sessionCookie = response.getHeaders (). get ("Set-Cookie"). get (0) .split (";") [0]; fejlécek = new HttpHeaders (); fejlécek.add ("Cookie", sessionCookie); httpEntity = új HttpEntity (fejlécek); válasz = testRestTemplate.exchange (testUrl + "/ rating-service / rating / all", HttpMethod.GET, httpEntity, String.class); Assert.assertEquals (HttpStatus.OK, response.getStatusCode ()); Assert.assertNotNull (response.getBody ());

Tesztünk egyre nagyobb! De futtatásakor láthatjuk, hogy rendszergazdaként bejelentkezve hozzáférést kapunk az adminisztrációs erőforráshoz.

Utolsó tesztünk az átjárónkon keresztül érhető el a felfedező szerverhez. Ehhez adja hozzá ezt a kódot a teszt végéhez:

response = testRestTemplate.exchange (testUrl + "/ discovery", HttpMethod.GET, httpEntity, String.class); Assert.assertEquals (HttpStatus.OK, response.getStatusCode ());

Futtassa ezt a tesztet még egyszer, hogy megerősítse, hogy minden működik. Siker!!!

Ezt hiányolta? Mivel bejelentkeztünk az átjáró szolgáltatásunkba, és megtekintettük könyvünk, minősítési és felfedezési szolgáltatásaink tartalmát anélkül, hogy négy külön szerverre kellett volna bejelentkeznünk!

Használatával Tavaszi ülés Hitelesítési objektumunk kiszolgálók között történő terjesztéséhez képesek vagyunk egyszer bejelentkezni az átjárón, és ezt a hitelesítést felhasználni a vezérlőkhöz való hozzáféréshez bármilyen számú háttérszolgáltatáson.

9. Következtetés

A biztonság a felhőben minden bizonnyal bonyolultabbá válik. De a segítségével Tavaszi biztonság és Tavaszi ülés, könnyedén megoldhatjuk ezt a kritikus kérdést.

Most egy felhőalkalmazás áll rendelkezésünkre biztonsággal a szolgáltatásaink körül. Használata Zuul és Tavaszi ülés csak egy szolgáltatásba tudunk naplózni és felhasználni a hitelesítést a teljes alkalmazásunkra. Ez azt jelenti, hogy könnyen feloszthatjuk alkalmazásunkat megfelelő domainekre, és mindegyiket biztonságossá tehetjük.

Mint mindig, a GitHubon megtalálja a forráskódot.