5. OAuth 2.0 erőforrás-kiszolgáló tavaszi biztonsággal
1. Áttekintés
Ebben az oktatóanyagban megtanuljuk hogyan állítsunk be egy OAuth 2.0 erőforrás-kiszolgálót a Spring Security 5 használatával.
Ezt a JWT, valamint az átlátszatlan tokenek, a Spring Security által támogatott kétféle hordozójelző használatával fogjuk megtenni.
Mielőtt folytatnánk a megvalósítást és a kódmintákat, megalapozunk néhány hátteret.
2. Egy kis háttér
2.1. Mik azok a JWT-k és az átlátszatlan tokenek?
A JWT vagy a JSON Web Token az érzékeny információk biztonságos továbbításának egyik módja a széles körben elfogadott JSON formátumban. A tartalmazott információk vonatkozhatnak a felhasználóra vagy magára a tokenre, például annak lejáratára és kibocsátójára.
Másrészt egy átlátszatlan jelző, amint a neve is sugallja, átlátszatlan az általa hordozott információk szempontjából. A token csak egy azonosító, amely az engedélyezési kiszolgálón tárolt információkra mutat - a kiszolgáló végén belüli ellenőrzésen keresztül érvényesül.
2.2. Mi az erőforrás-kiszolgáló?
Az OAuth 2.0 kontextusában a Az erőforrás-kiszolgáló olyan alkalmazás, amely az erőforrásokat OAuth-tokeneken keresztül védi. Ezeket a tokeneket egy hitelesítési szerver adja ki, általában egy kliens alkalmazás számára. Az erőforrás-kiszolgáló feladata a token ellenőrzése, mielőtt egy erőforrást kiszolgálna az ügyfélnek.
A token érvényességét több dolog határozza meg:
- Ez a token a konfigurált jogosultságkiszolgálótól származik?
- Lejárt?
- Ez az erőforrás-kiszolgáló a kívánt közönség?
- A token rendelkezik a szükséges jogosultsággal a kért erőforráshoz való hozzáféréshez?
A megjelenítéshez nézzük meg az engedélyezési kód folyamatának sorrendjét, és nézzük meg az összes szereplőt:
Amint azt a 8. lépésben láthatjuk, amikor az ügyfélalkalmazás felhívja az erőforrás-kiszolgáló API-ját egy védett erőforráshoz való hozzáféréshez, először az engedélyezési kiszolgálóhoz megy, hogy ellenőrizze a kérelemben szereplő tokent. Engedély: Viselő fejlécet, majd válaszol az ügyfélnek.
A 9. lépésre koncentrálunk ebben az oktatóanyagban.
Rendben, most ugorjunk bele a kódrészbe. Hitelesítési kiszolgálót hozunk létre a Keycloak, egy erőforrás-kiszolgáló, amely ellenőrzi a JWT-tokeneket, egy másik erőforrás-kiszolgáló, amely ellenőrzi az átlátszatlan tokenek használatát, és néhány JUnit-teszt az ügyfélalkalmazások szimulálására és a válaszok ellenőrzésére.
3. Engedélyezési kiszolgáló
Először felállítunk egy engedélyezési kiszolgálót, vagy a tokeneket kiadó dolgot.
Ehhez a Spring Boot alkalmazásba ágyazott Keycloak-ot fogjuk használni. A Keycloak egy nyílt forráskódú identitás- és hozzáférés-kezelési megoldás. Mivel ebben az oktatóanyagban az erőforrás-kiszolgálóra összpontosítunk, nem foglalkozunk mélyebben vele.
Beágyazott Keycloak szerverünk két klienst definiál - fooClient és barClient - megfelel a két erőforrás-kiszolgáló alkalmazásunknak.
4. Erőforrás-kiszolgáló - JWT-k használata
Erőforrás-kiszolgálónknak négy fő összetevője lesz:
- Modell - a védelemre szánt erőforrás
- API - REST vezérlő az erőforrás leleplezéséhez
- Biztonsági konfiguráció - osztály, amely meghatározza az API által kitett védett erőforrás hozzáférés-vezérlését
- alkalmazás.yml - konfigurációs fájl a tulajdonságok deklarálásához, beleértve az engedélyezési kiszolgálóval kapcsolatos információkat
Lássuk őket egyesével az erőforrás-kiszolgálónkon, amely JWT-tokeneket kezel, miután lestünk a függőségekről.
4.1. Maven-függőségek
Főleg szükségünk lesz a spring-boot-starter-oauth2-erőforrás-kiszolgáló, A Spring Boot indítója az erőforrás-kiszolgálók támogatásához. Ez az indító alapértelmezés szerint tartalmazza a Spring Security szolgáltatást, ezért nem kell kifejezetten hozzáadnunk:
org.springframework.boot spring-boot-starter-web 2.2.6.RELEASE org.springframework.boot spring-boot-starter-oauth2-resource-server 2.2.6.RELEASE org.apache.commons commons-lang3 3.9
Ezen kívül webes támogatást is felvettünk.
Bemutató céljainkhoz az erőforrásokat véletlenszerűen generáljuk ahelyett, hogy adatbázisból kapnánk őket, némi segítséggel az Apache-tól commons-lang3 könyvtár.
4.2. Modell
Az egyszerűség kedvéért felhasználjuk Foo, POJO, mint védett erőforrásunk:
nyilvános osztály Foo {private long id; privát karakterlánc neve; // kivitelező, mérőeszközök és beállítók}
4.3. API
Itt van a többi vezérlőnk Foo manipulálható:
@RestController @RequestMapping (value = "/ foos") public class FooController {@GetMapping (value = "/ {id}") public Foo findOne (@PathVariable Long id) {return new Foo (Long.parseLong (randomNumeric (2)) ), véletlenszerű ábécé (4); } @GetMapping public List findAll () {List fooList = new ArrayList (); fooList.add (új Foo (Long.parseLong (randomNumeric (2), randomAfabetic (4))); fooList.add (új Foo (Long.parseLong (randomNumeric (2), randomAfabetic (4))); fooList.add (új Foo (Long.parseLong (randomNumeric (2), randomAfabetic (4))); return fooList; } @ResponseStatus (HttpStatus.CREATED) @PostMapping public void create (@RequestBody Foo newFoo) {logger.info ("Foo létrehozva"); }}
Mint nyilvánvaló, rendelkezésünkre áll a GET all Foos, GET a Foo id alapján, és POST a Foo.
4.4. Biztonsági konfiguráció
Ebben a konfigurációs osztályban meghatározzuk az erőforrásunk hozzáférési szintjeit:
A @Configuration nyilvános osztályú JWTSecurityConfig kiterjeszti a WebSecurityConfigurerAdapter {@Orride védett érvénytelen konfigurációját (HttpSecurity http) a Kivételt dobja: {http .authorizeRequests (authz -> authz .antMatchers (HttpMethod.GET, "/foos/**"))has .antMatchers (HttpMethod.POST, "/foos").hasAuthority("SCOPE_write") .anyRequest (). hitelesítve ()) .oauth2ResourceServer (oauth2 -> oauth2.jwt ()); }}
Akinek van hozzáférési tokenje, rendelkezik a olvas hatókör kaphat Foos. Annak érdekében, hogy POST egy új Foo, a tokenjüknek rendelkeznie kell egy ír hatálya.
Ezenkívül hívást adtunk a jwt () használni a oauth2ResourceServer () DSL itt jelzi a szerverünk által támogatott tokenek típusát.
4.5. alkalmazás.yml
Az alkalmazás tulajdonságaiban a szokásos portszám és a kontextus-elérési út mellett meg kell határoznunk az engedélyezési kiszolgálónk kibocsátói URI elérési útját, hogy az erőforrás-kiszolgáló felfedezhesse szolgáltatójának konfigurációját:
szerver: port: 8081 servlet: context-path: / resource-server-jwt spring: biztonság: oauth2: resourceserver: jwt: kibocsátó-uri: // localhost: 8083 / auth / realms / baeldung
Az erőforrás-kiszolgáló ezeket az információkat felhasználja az ügyfélalkalmazásból érkező JWT-tokenek hitelesítésére a sorrenddiagramunk 9. lépése szerint.
Ahhoz, hogy ez az érvényesítés a kibocsátó-uri tulajdonság, az engedélyezési szervernek működnie kell. Ellenkező esetben az erőforrás-kiszolgáló nem indul el.
Ha önállóan kell elindítanunk, akkor a jwk-set-uri tulajdonság helyett az engedélyezési kiszolgáló nyilvános kulcsokat kitevő végpontjára mutat:
jwk-set-uri: // localhost: 8083 / auth / realms / baeldung / protokoll / openid-connect / certs
És csak erre van szükségünk ahhoz, hogy szerverünk érvényesítse a JWT tokeneket.
4.6. Tesztelés
Tesztelés céljából létrehozunk egy JUnit-et. Ennek a tesztnek a végrehajtásához szükségünk van az engedélyezési kiszolgálóra, valamint az erőforrás-kiszolgálóra.
Ellenőrizzük, hogy megkapjuk-e Foos től erőforrás-kiszolgáló-jwt a-val olvas hatókörű token a tesztünkben:
@Test public void givenUserWithReadScope_whenGetFooResource_thenSuccess () {String accessToken = iegūtAccessToken ("olvasni"); Válaszválasz = RestAssured.given () .header (HttpHeaders.AUTHORIZATION, "Bearer" + accessToken) .get ("// localhost: 8081 / resource-server-jwt / foos"); assertThat (response.as (List.class)). hasSizeGreaterThan (0); }
A fenti kódban a 3. sorban hozzáférési tokent kapunk a olvas hatókör az engedélyezési kiszolgálótól, amely lefedi a sorrenddiagramunk 1–7. lépéseit.
A 8. lépést a RestAssured’S kap() hívás. A 9. lépést az erőforrás-kiszolgáló hajtja végre az általunk látott konfigurációkkal, és átlátható számunkra, mint felhasználók számára.
5. Erőforrás-kiszolgáló - átlátszatlan tokenek használata
Ezután nézzük meg ugyanazokat az összetevőket az átlátszatlan tokenek kezelésével foglalkozó erőforrás-kiszolgálónk esetében.
5.1. Maven-függőségek
Az átlátszatlan tokenek támogatásához szükségünk lesz ezekre is oauth2-oidc-sdk függőség:
com.nimbusds oauth2-oidc-sdk 8.19 futásidejű
5.2. Modell és vezérlő
Ehhez hozzáadunk egy Rúd forrás:
public class Bar {private long id; privát karakterlánc neve; // kivitelező, mérőeszközök és beállítók}
Nálunk is lesz egy BarController a mi végünkhöz hasonló végpontokkal FooController előtt, hogy kitálaljon Rúds.
5.3. alkalmazás.yml
Ban,-ben alkalmazás.yml itt hozzá kell adnunk egy önvizsgálat-uri megfelel a hitelesítési kiszolgálónk önellenőrzési végpontjának. Mint korábban említettük, egy átlátszatlan tokent érvényesítenek: A hozzáférési szintek hasonló fenntartása a Foo a Rúd erőforrás is, ez a konfigurációs osztály hívást is kezdeményez opaqueToken () használni a oauth2ResourceServer () DSL az átlátszatlan token típus használatának jelzésére: Itt adjuk meg az engedélyezési kiszolgáló által használt kliensnek megfelelő ügyfél-hitelesítő adatokat is. Ezeket korábban a következőkben definiáltuk alkalmazás.yml. Létrehozunk egy JUnit-t az átlátszatlan token-alapú erőforrás-kiszolgálónkhoz, hasonlóan ahhoz, ahogyan a JWT-hez. Ebben az esetben ellenőrizzük, hogy a ír hatókörű hozzáférési token POST lehet Rúd nak nek erőforrás-szerver-átlátszatlan: Ha a CREATED állapotot visszakapjuk, az azt jelenti, hogy az erőforrás-kiszolgáló sikeresen ellenőrizte az átlátszatlan tokent, és létrehozta a Rúd nekünk. Ebben az oktatóanyagban láthattuk, hogyan kell konfigurálni a Spring Security alapú erőforrás-kiszolgáló alkalmazást a JWT és az átlátszatlan tokenek érvényesítésére. Ahogy láttuk, minimális beállítással Spring lehetővé tette a tokenek zökkenőmentes hitelesítését egy kibocsátóval és küldjön erőforrásokat a kérelmező félnek - esetünkben JUnit teszt. Mint mindig, a forráskód is elérhető a GitHubon.szerver: port: 8082 servlet: context-path: / erőforrás-kiszolgáló-átlátszatlan rugó: biztonság: oauth2: erőforrás-kiszolgáló: átlátszatlan: introspekció-uri: // localhost: 8083 / auth / realms / baeldung / protokoll / openid-connect / token / introspect introspection-client-id: barClient introspection-client-secret: barClientSecret
5.4. Biztonsági konfiguráció
A @Configuration public class OpaqueSecurityConfig kiterjeszti a WebSecurityConfigurerAdapter {@Value ("$ {spring.security.oauth2.resourceserver.opaque.introspection-uri}") String introspectionUri; @Value ("$ {spring.security.oauth2.resourceserver.opaque.introspection-client-id}") Karakterlánc clientId; @Value ("$ {spring.security.oauth2.resourceserver.opaque.introspection-client-secret}") Karakterlánc clientSecret; A @Orride protected void configure (HttpSecurity http) a {http .authorizeRequests (authz -> authz .antMatchers (HttpMethod.GET, "/bars/**").hasAuthority("SCOPE_read") .antMatchers (HttpMethod.POST, /bars").hasAuthority("SCOPE_write ") .anyRequest (). hitelesített ()) .oauth2ResourceServer (oauth2 -> oauth2 .opaqueToken (token -> token.introspectionUri (this.introspectionUri) .introspentClient.introspectionClient. clientSecret))); }}
5.5. Tesztelés
@Test public void givenUserWithWriteScope_whenPostNewBarResource_thenCreated () {String accessToken = iegūtAccessToken ("olvasási írás"); Bar newBar = új Bar (Long.parseLong (randomNumeric (2)), randomAfabetic (4)); Válaszválasz = RestAssured.given () .contentType (ContentType.JSON) .header (HttpHeaders.AUTHORIZATION, "Bearer" + accessToken) .body (newBar) .log () .all () .post ("// localhost: 8082 / resource-server-opaque / bars "); assertThat (response.getStatusCode ()). isEqualTo (HttpStatus.CREATED.value ()); }
6. Következtetés