A JWT használata a Spring Security OAuth használatával

1. Áttekintés

Ebben az oktatóanyagban megvitatjuk, hogyan szerezhetjük be a Spring Security OAuth2 bevezetésünket a JSON web tokenek használatára.

Az OAuth sorozat tavaszi REST API + OAuth2 + Angular cikkének tetejére is építünk.

2. Az OAuth2 Authorization Server

Korábban a Spring Security OAuth verem lehetőséget kínált egy Authorization Server telepítésére tavaszi alkalmazásként. Ezután konfigurálnunk kellett a használatra JwtTokenStore hogy JWT tokeneket használhassunk.

Az OAuth-verem azonban Spring elavult, és most a Keycloak-ot fogjuk használni hitelesítési kiszolgálónkként.

Tehát ezúttal be fogjuk állítani az Engedélyezési kiszolgálót beágyazott Keycloak szerverként egy Spring Boot alkalmazásban. Alapértelmezés szerint JWT tokent ad ki, ezért nincs szükség más konfigurációra ebben a tekintetben.

3. Erőforrás-kiszolgáló

Most nézzük meg, hogyan konfigurálhatjuk az erőforrás-kiszolgálónkat a JWT használatára.

Megcsináljuk ezt egy alkalmazás.yml fájl:

szerver: port: 8081 servlet: context-path: / erőforrás-kiszolgáló rugó: security: oauth2: resourceserver: jwt: kibocsátó-uri: // localhost: 8083 / auth / realms / baeldung jwk-set-uri: // localhost: 8083 / auth / realms / baeldung / protocol / openid-connect / certs

A JWT-k az összes információt tartalmazzák a tokenben. Tehát az erőforrás-kiszolgálónak ellenőriznie kell a token aláírását, hogy megbizonyosodjon arról, hogy az adatok nem módosultak-e. A jwk-set-uri ingatlan tartalmazza a nyilvános kulcsot amelyet a szerver használhat erre a célra.

A kibocsátó-uri tulajdonság az alap Authorization Server URI-ra mutat, amely szintén felhasználható a iss követelés, mint hozzáadott biztonsági intézkedés.

Továbbá, ha a jwk-set-uri tulajdonság nincs beállítva, az Erőforrás-kiszolgáló megpróbálja használni a kibocsátó-ui ennek a kulcsnak a meghatározásához az Authorization Server metaadat-végpontból.

Fontos, hogy a kibocsátó-uri vagyon arra kötelezi a Resource Server alkalmazás elindítása előtt futnia kell az Authorization Server-nek.

Most nézzük meg, hogyan állíthatjuk be a JWT támogatást a Java konfiguráció segítségével:

A @Configuration public class SecurityConfig kiterjeszti a WebSecurityConfigurerAdapter {@Orride védett érvénytelen konfigurációt (HttpSecurity http) a {http.cors () .and () .authorizeRequests () .antMatchers (HttpMethod.GET, "/ user / info", "/ api / foos / ** ") .hasAuthority (" SCOPE_read ") .antMatchers (HttpMethod.POST," / api / foos ") .hasAuthority (" SCOPE_write ") .anyRequest () .authenticated () .and () .oauth2ResourceServer ). jwt (); }}

Itt felülbíráljuk az alapértelmezett Http Security konfigurációt. Tehát ezt kifejezetten meg kell határoznunk azt akarjuk, hogy ez erőforrás-kiszolgálóként viselkedjen, és hogy JWT-formátumú hozzáférési tokent fogunk használni a oauth2ResourceServer () és jwt ()illetőleg.

A fenti JWT konfiguráció az alapértelmezett Spring Boot példány biztosítja számunkra. Ez testreszabható is, amint hamarosan látni fogjuk.

4. Egyéni követelések a tokenben

Most hozzunk létre egy infrastruktúrát, hogy néhányat hozzá tudjunk adni az Engedélyezési kiszolgáló által visszaküldött egyéni jogcímek az Access Tokenben. A keretrendszer által biztosított szokásos követelések rendben vannak, de legtöbbször szükségünk lesz néhány kiegészítő információra a tokenben, hogy ezeket az Ügyfél oldalán felhasználhassuk.

Vegyünk egy példát egy egyéni követelésre, szervezet, amely tartalmazza az adott felhasználói szervezet nevét.

4.1. Engedélyezési kiszolgáló konfigurálása

Ehhez hozzá kell adnunk néhány konfigurációt a birodalmi definíciós fájlunkhoz, baeldung-realm.json:

  • Adjon hozzá egy attribútumot szervezet felhasználónknak [e-mail védett]:
    "attributes": {"szervezet": "baeldung"},
  • Adja hozzá a protokollMapper hívott szervezet hoz jwtClient konfiguráció:
    "protokollMappers": [{"id": "06e5fc8f-3553-4c75-aef4-5a4d7bb6c0d1", "név": "szervezet", "protokoll": "openid-connect", "protocolMapper": "oidc-usermodel-attribútum -mapper "," hozzájárulásRequired ": hamis," config ": {" userinfo.token.claim ":" true "," user.attribute ":" szervezet "," id.token.claim ":" true "," access.token.claim ":" true "," igénylési név ":" szervezet "," jsonType.label ":" Karakterlánc "}}],

A Keycloak önálló beállításához ez a Felügyeleti konzol segítségével is elvégezhető.

Ezenkívül fontos megjegyezni ezt a fenti JSON-konfiguráció a Keycloakra jellemző, és más OAuth-kiszolgálókon eltérő lehet.

Ezzel az új konfigurációval és futtatásával kapunk egy extra attribútumot szervezet = baeldung, a token hasznos terhelésében [e-mail védett]:

{jti: "989ce5b7-50b9-4cc6-bc71-8f04a639461e" exp: 1585242462 nbf: 0 iat: 1585242162 iss: "// localhost: 8083 / auth / realms / baeldung" al: "a5461470-33eb-4b2d-82d4 -048 "typ:" Bearer "azp:" jwtClient "auth_time: 1585242162 session_state:" 384ca5cc-8342-429a-879c-c15329820006 "acr:" 1 "hatókör:" profilírás olvasás "szervezet:" baeldung "preferált_felhasználónév:" [e-mail védett ] "}

4.2. Használja az Access Tokent az Angular Client alkalmazásban

Ezután ki akarjuk használni a Token információkat az Angular Client alkalmazásban. Ehhez az angular2-jwt könyvtárat fogjuk használni.

Ki fogjuk használni a szervezet követelés a mi AppService, és adjon hozzá egy függvényt getOrganization:

getOrganization () {var token = Cookie.get ("access_token"); var hasznos terhelés = this.jwtHelper.decodeToken (token); this.organization = hasznos teher.organization; adja vissza ezt.szervezés; }

Ez a funkció a JwtHelperService tól szögletes2-jwt könyvtár az Access Token dekódolásához és az egyedi követelés megszerzéséhez. Most már csak annyit kell tennünk, hogy megjelenítjük a mi AppComponent:

@Component ({selector: 'app-root', sablon: `Spring Security Oauth - Engedélyezési kód 

{{szervezet}}

`}) export osztály Az AppComponent megvalósítja az OnInit {public organization =" "; konstruktor (magánszolgáltatás: AppService) {} ngOnInit () {this.organization = this.service.getOrganization (); }}

5. Hozzáférés az extra követelésekhez az erőforrás-kiszolgálón

De hogyan férhetünk hozzá ezekhez az információkhoz a Resource Server oldalon?

5.1. Hozzáférés a Hitelesítési kiszolgáló követeléseihez

Ez nagyon egyszerű: csak nekünk kell kivonat a org.springframework.security.oauth2.jwt.Jwt’S AuthenticationPrincalal, mint bármely más attribútum esetében tennénk UserInfoController:

@GetMapping ("/ user / info") public getUserInfo Map (@AuthenticationPrincipal Jwt principál) {Map map = új Hashtable (); map.put ("felhasználó_neve", fő.getClaimAsString ("preferált_felhasználónév")); map.put ("szervezet", fő.getClaimAsString ("szervezet")); return Gyűjtemények.unmodifiableMap (térkép); } 

5.2. Konfiguráció a követelések hozzáadásához / eltávolításához / átnevezéséhez

Most mi van, ha további igényeket akarunk hozzáadni az Erőforrás-kiszolgáló oldalon? Vagy eltávolít vagy átnevez néhányat?

Tegyük fel, hogy módosítani szeretnénk a szervezet a hitelesítési kiszolgálótól érkező igény, hogy az értéket nagybetűvel kapja meg. Ezenkívül, ha a követelés nem szerepel a felhasználónál, akkor annak értékét kell beállítanunk ismeretlen.

Ennek eléréséhez először is meg kell tennünk adjon hozzá egy osztályt, amely végrehajtja a Átalakító interfész és felhasználások MappedJwtClaimSetConverter követelések konvertálásához:

public class OrganizationSubClaimAdapter megvalósítja a konvertert {private final MappedJwtClaimSetConverter delegate = MappedJwtClaimSetConverter.withDefaults (Collections.emptyMap ()); public Map convert (Térképigények) {Map convertClaims = this.delegate.convert (követelések); Karaktersorozat = convertClaims.get ("szervezet")! = Null? (String) convertClaims.get ("szervezet"): "ismeretlen"; convertClaims.put ("szervezet", organization.toUpperCase ()); return convertClaims; }}

Másodszor, a mi SecurityConfig osztályban kell adjuk hozzá a sajátunkat JwtDecoder példa hogy felülbírálja a Spring Boot által biztosítottat és állítsa be a mi OrganizationSubClaimAdapter mint követelés-átalakítója:

@Bean public JwtDecoder customDecoder (OAuth2ResourceServerProperties tulajdonságok) {NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withJwkSetUri (properties.getJwt (). GetJwkSetUri ()). jwtDecoder.setClaimSetConverter (új OrganizationSubClaimAdapter ()); return jwtDecoder; } 

Most, amikor eltaláltuk /Felhasználói adatok API a felhasználó számára [e-mail védett], megkapjuk a szervezet mint ISMERETLEN.

Ne feledje, hogy felülírja az alapértelmezettet JwtDecoder A Spring Boot által konfigurált babot gondosan kell elvégezni, hogy az összes szükséges konfigurációt továbbra is tartalmazza.

6. Kulcsok betöltése Java kulcstárból

Korábbi konfigurációnkban a Jogosultságkiszolgáló alapértelmezett nyilvános kulcsát használtuk a token integritásának ellenőrzésére.

Az aláírási folyamat elvégzéséhez a Java Keystore fájlban tárolt kulcspár és tanúsítvány is használható.

6.1. JKS Java KeyStore fájl létrehozása

Először generáljuk a kulcsokat - pontosabban a .jks fájl - a parancssori eszköz használatával kulcstartó:

keytool -genkeypair -alias mytest -keyalg RSA -keypass mypass -keystore mytest.jks -storepass mypass

A parancs létrehoz egy nevű fájlt mytest.jks amely tartalmazza a kulcsainkat - a nyilvános és a privát kulcsokat.

Ügyeljen arra is keypass és raktár ugyanazok.

6.2. Nyilvános kulcs exportálása

Ezután exportálnunk kell a nyilvános kulcsunkat a létrehozott JKS-ből, ehhez a következő parancsot használhatjuk:

keytool -list -rfc --keystore mytest.jks | openssl x509 -inform pem -pubkey

A válaszminta így fog kinézni:

----- BEGIN NYILVÁNOSKULCS ----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgIK2Wt4x2EtDl41C7vfp OsMquZMyOyteO2RsVeMLF / hXIeYvicKr0SQzVkodHEBCMiGXQDz5prijTq3RHPy2 / 5WJBCYq7yHgTLvspMy6sivXN7NdYE7I5pXo / KHk4nz + Fa6P3L8 + L90E / 3qwf6j3 DKWnAgJFRY8AbSYXt1d5ELiIG1 / gEqzC0fZmNhhfrBtxwWXrlpUDT0Kfvf0QVmPR xxCLXT + tEe1seWGEqeOLL5vXRLqmzZcBe1RZ9kQQm43 + a9Qn5icSRnDfTAesQ3Cr lAWJKl2kcWU1HwJqw + dZRSZ1X4kEXNMyzPdPBbGmU6MHdhpywI7SKZT7mX4BDnUK eQIDAQAB ----- END NYILVÁNOSKULCS --- - ----- BEGIN CERTIFICATE ----- MIIDCzCCAfOgAwIBAgIEGtZIUzANBgkqhkiG9w0BAQsFADA2MQswCQYDVQQGEwJ1 czELMAkGA1UECBMCY2ExCzAJBgNVBAcTAmxhMQ0wCwYDVQQDEwR0ZXN0MB4XDTE2 MDMxNTA4MTAzMFoXDTE2MDYxMzA4MTAzMFowNjELMAkGA1UEBhMCdXMxCzAJBgNV BAgTAmNhMQswCQYDVQQHEwJsYTENMAsGA1UEAxMEdGVzdDCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAICCtlreMdhLQ5eNQu736TrDKrmTMjsrXjtkbFXj Cxf4VyHmL4nCq9EkM1ZKHRxAQjIhl0A8 + aa4o06t0Rz8tv + ViQQmKu8h4Ey77KTM urIr1zezXWBOyOaV6Pyh5OJ8 / hWuj9y / Pi / dBP96sH + o9wylpwICRUWPAG0mF7dX eRC4iBtf4BKswtH2ZjYYX6wbccFl65aVA09Cn739EFZj0ccQi10 / rRHtbHlhhKnj i y + b10S6ps2XAXtUWfZEEJuN / mvUJ + YnEkZw30wHrENwq5QFiSpdpHFlNR8CasPn WUUmdV + JBFzTMsz3TwWxplOjB3YacsCO0imU + 5l + AQ51CnkCAwEAAaMhMB8wHQYD VR0OBBYEFOGefUBGquEX9Ujak34PyRskHk + WMA0GCSqGSIb3DQEBCwUAA4IBAQB3 1eLfNeq45yO1cXNl0C1IQLknP2WXg89AHEbKkUOA1ZKTOizNYJIHW5MYJU / zScu0 yBobhTDe5hDTsATMa9sN5CPOaLJwzpWV / ZC6WyhAWTfljzZC6d2rL3QYrSIRxmsp / J1Vq9WkesQdShnEGy7GgRgJn4A8CKecHSzqyzXulQ7Zah6GoEUD + vjb + BheP4aN hiYY1OuXD + HsdKeQqS + 7eM5U7WW6dz2Q8mtFJ5qAxjY75T0pPrHwZMlJUhUZ + Q2V FfweJEaoNB9w9McPe1cAiE + oeejZ0jq0el3 / dJsx3rlVqZN + lMhRJJeVHFyeb3XF lLFCUGhA7hxn2xf3x1JW ----- END BIZONYÍTVÁNY-----

6.3. Maven konfiguráció

Ezután nem akarjuk, hogy a JKS fájlt a maven szűrési folyamat vegye fel - ezért biztosan kizárjuk a pom.xml:

   src / main / resources true * .jks 

Ha a Spring Boot alkalmazást használjuk, meg kell győződnünk arról, hogy a JKS fájlunkat hozzáadtuk az alkalmazás osztályához a Spring Boot Maven beépülő modulon keresztül - addResources:

   org.springframework.boot spring-boot-maven-plugin true 

6.4. Authorization Server

Most konfiguráljuk a Keycloak alkalmazást a Keypair from -tól mytest.jks, hozzáadva a tartomány definíciós JSON fájljaihoz KeyProvider szakasz az alábbiak szerint:

{"id": "59412b8d-aad8-4ab8-84ec-e546900fc124", "name": "java-keystore", "szolgáltatóId": "java-keystore", "subComponents": {}, "config": {" keystorePassword ": [" mypass "]," keyAlias ​​": [" mytest "]," keyPassword ": [" mypass "]," active ": [" true "]," keystore ": [" src / main / resources /mytest.jks "]," prioritás ": [" 101 "]," engedélyezve ": [" igaz "]," algoritmus ": [" RS256 "]}},

Itt állítottuk be a kiemelten fontos nak nek 101, nagyobb, mint bármely más Keypair a hitelesítési kiszolgálónk számára, és állítsa be aktív nak nek igaz. Ez annak biztosítására szolgál, hogy az erőforrás-kiszolgálónk kiválassza ezt a bizonyos Keypairt a jwk-set-uri tulajdonság, amelyet korábban megadtunk.

Ez a konfiguráció megint csak a Keycloakra vonatkozik, és eltérhet az OAuth Server más megvalósításaitól.

7. Következtetés

Ebben a rövid cikkben arra összpontosítottunk, hogy beállítsuk a Spring Security OAuth2 projektünket a JSON Web Tokenek használatára.

Az oktatóanyag teljes megvalósítása a GitHub oldalon található.