Java REST API Showdown: melyik a legjobb keret a piacon?

A Java-ban a szolgáltatások fejlesztése, beleértve a REST API-kat is, nem volt mindig könnyű vagy produktív, amíg a tavasz meg nem jött, és megváltoztatta a tájat. Azóta sok év telt el, és új keretek alakultak ki a közösségben.

az egyik ilyen keretrendszer a Micronaut volt. Az OCI fejlesztette ki, ugyanaz a cég a Grails mögött, és céljuk, hogy segítsék a fejlesztőket mikroszolgáltatások és szerver nélküli alkalmazások létrehozásában.

van még Quarkus, egy másik keret, amely népszerűvé vált az elmúlt évben. A RedHat által kifejlesztett Quarkus gyors indítást és kevesebb memóriahasználatot ígér, két gyakori probléma a Java REST szolgáltatások fejlesztésekor.

ezekkel a választásokkal nagyon fontos kérdés merül fel: mennyire könnyű létrehozni egy szolgáltatást e három keretrendszer mindegyikével?

ebben az oktatóanyagban létrehoz egy biztonságos pihenő alkalmazást a Spring, Micronaut és Quarkus segítségével, hogy megtudja, hogyan különböznek egymástól, és melyik felel meg legjobban az Ön igényeinek.

Tartalomjegyzék

  • Előfeltételei A Java rest API
    • hozzon Létre egy Okta Számla Felhasználó Menedzsment
    • Generál Token Használatával OpenID Csatlakoztassa Debugger
  • Építeni egy Java rest API-val Micronaut
    • Fejleszteni A Java Szolgáltatás
  • Építeni egy Java rest API-val Quarkus
  • Építeni egy Java rest API a Tavaszi Boot
  • Utolsó Gondolatai a TÖBBI Api A Java: Micronaut, Quarkus, valamint a Tavaszi Boot

Ha szeretném, meg lehet nézni, hogy ez a bemutató, mint egy screencast. 👇

előfeltételei a Java REST API

Ez a bemutató használ Maven 3+. A folytatás előtt ellenőrizze, hogy telepítve van-e és használható-e. Akkor biztosan is használja Gradle, de YMMV.

olyan alkalmazásokat fog létrehozni, amelyek hitelesítik a kéréseket az OAuth 2.0 használatával, amelyet egy Okta alkalmazás biztosít. Nincs Okta-fiókja? Ne aggódj, kevesebb, mint egy perc, hogy hozzon létre egy újat. Nem csak, hogy, de Okta támogatja szabványok, mint a JWT, OAuth 2.0, OIDC. Olyan jól ismert keretrendszereket támogatunk, mint a Java EE, a Spring Boot vagy a Spring Security. Heck, mi is van egy Maven plugin, amely automatizálja mindent az Ön számára.

nincs szükség újra feltalálni a kereket!

hozzon létre egy Okta-fiókot a felhasználói kezeléshez

nyissa meg a terminált, majd hajtsa végre a következő parancsot:

mvn com.okta:okta-maven-plugin:register

meg kell adnia a következő információkat:

  • Keresztnév
  • vezetéknév
  • Email
  • vállalat

miután megválaszolta a kérdéseket, e-mailt kap a vadonatúj fiók aktiválásához. A fiók aktiválása után futtassa a következő parancsot:

mvn com.okta:okta-maven-plugin:spring-boot

Ez a parancs létrehoz egy alkalmazást az Ön számára az auth kódfolyammal és a Spring Security átirányítási URI-jával az Okta számára.

Okta Maven által generált alkalmazás

hogy jobban emlékezzen rá, ugyanazt az alkalmazást manuálisan is létrehozhatja:

  • nyissa meg az Okta fejlesztői honlapját, majd jelentkezzen be fiókjába.
  • kattintson az Alkalmazásokra> Alkalmazás hozzáadása> Web> tovább.

a következő képernyő jelenik meg:

okta új alkalmazás

mielőtt folytatná, hajtsa végre a következő változtatásokat az alkalmazásban:

  • Login redirect URIs:
    • http://localhost:8080/login/oauth2/code/okta
    • https://oidcdebugger.com/debug
  • Grant típus engedélyezett
    • Engedélyezési Kód
    • Implicit (Hibrid)

A közvetett támogatás típusa (ID, illetve Access Token engedélyezett ellenőrzött) szükséges letölteni egy access token a böngészőben.

a fent nem említett mezők megtarthatják alapértelmezett értékeiket.

miután befejezte, kattintson a Kész gombra. Az alkalmazás készen áll!

a következő lépés az, hogy megtanulják, hogyan kell létrehozni egy érvényes token segítségével.

tokenek generálása az OpenID Connect Debugger

Okta segítségével a felhőben lévő felhasználókat API-k segítségével kezelheti. Lehetővé teszi az alkalmazások biztonságos használatát az OAuth 2.0 és az OpenID Connect (más néven OIDC) használatával is. Az OAuth 2.0 mechanizmust biztosít a felhatalmazáson alapuló engedélyezéshez, ami azt jelenti, hogy nem kell tárolnia a felhasználói hitelesítő adatokat az alkalmazásban. Ehelyett ezt átruházhatja egy OAuth 2.0 szolgáltatóra (Okta, ebben az esetben). Az OIDC identitásréteget biztosít az OAuth 2.0 tetején, ezért az Okta-hoz hasonló vállalatokat “identitásszolgáltatóknak” vagy IdPs-nek hívják.

regisztrálta az alkalmazást az Okta-val, most pedig létrehozhat egy tokent, hogy hozzáférjen hozzá. Az egyik regisztrált bejelentkezési átirányítási URI az OpenID Connect webhelyre vonatkozik.

a kéréseket egy token segítségével érvényesítjük. Ennek a tokennek a létrehozásához az OpenID Connect hibakeresőt fogja használni. Ez a weboldal egy egyszerű módja annak, hogy hitelesítő adatokat generáljon az Okta alkalmazásban lévő felhasználók számára.

menjen a https://oidcdebugger.com és töltse ki a következő információkat:

  • Uri engedélyezése: https://{yourOktaDomain}/oauth2/default/v1/authorize
  • : https://oidcdebugger.com/debug
  • – Ügyfél ID: {yourOktaClientId}
  • Hatálya: openid email profile
  • Állapot: dev
  • Pedofil: (tartsa meg az alapértelmezett érték)
  • Válasz típus: token

megtalálja az értéket a {yourOktaDomain} a jobb felső sarokban a fiók honlap: Okta Honlap

ahhoz, Hogy megtalálja a Okta Ügyfél AZONOSÍTÓ kövesse az alábbi lépéseket,:

  • Go to Applications
  • Select My Web App
  • Click General

az Ügyfélazonosító elérhető lesz a kliens hitelesítő adatok szakaszban:

ügyfél hitelesítő adatok

az összes mező kitöltése után kattintson a Kérés küldése gombra. A rendszer átirányítja Önt az Okta bejelentkezési oldalára.

a sikeres hitelesítés után újra átirányítja Önt az OIDC Debugger-re, ahol láthatja a generált tokent:

generált Token

ezt a tokent fogja használni a építeni kívánt szolgáltatások biztonságos eléréséhez.

most, hogy van Okta-fiókod, és tudod, hogyan kell tokeneket generálni az Okta alkalmazásod segítségével, kezdjük el összehasonlítani a keretrendszereket!

Készítsen Java REST API-t Micronaut

a Micronaut szolgáltatás fejlesztésének első lépése az SDKMAN letöltése!. SDKMAN! a több SDK párhuzamos verzióinak kezelésére szolgáló eszköz, amelyet a Micronaut kliens telepítéséhez használ.

lehet letölteni SDKMAN! a következő parancs futtatásával:

curl -s https://get.sdkman.io | bash

most már maga a Micronaut is telepíthető. Csak futtassa a következő parancsot a terminálon:

sdk install micronaut

a parancs végrehajtása után a legújabb Micronaut verzió elérhető a számítógépen.

készen áll az alkalmazás fejlesztésére!

fejlessze Java szolgáltatását

LÉPJEN az alkalmazást létrehozni kívánt könyvtárba, majd hajtsa végre a következő parancsot:

mn create-app com.okta.rest.app --build maven

Ez a parancs létrehoz egy projektet egy Micronaut projekt alapszerkezetével. Micronaut használja Gradle alapértelmezés szerint, de mivel te használ --build maven, akkor használja Maven helyett.

a következő lépés a biztonsági könyvtárak hozzáadása a projekten belül. Szerkessze apom.xml fájlt és adja hozzá a következő függőségeket:

<dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-security</artifactId></dependency><dependency> <groupId>io.micronaut</groupId> <artifactId>micronaut-security-jwt</artifactId></dependency>

ezek a függőségek lehetővé teszik a biztonságot – különösen OAuth 2.0 a JWT – vel-a projekten belül. Most, hogy az összes függőség a helyén van, elkezdheti létrehozni a végpontot.

hozza létre a következő osztályt a src/main/java/com/okta/rest/controller:

package com.okta.rest.controller;import io.micronaut.http.MediaType;import io.micronaut.http.annotation.Controller;import io.micronaut.http.annotation.Get;import io.micronaut.http.annotation.Produces;import io.micronaut.security.annotation.Secured;import io.micronaut.security.rules.SecurityRule;import java.security.Principal;@Controller("/hello")public class HelloController { @Get @Secured(SecurityRule.IS_AUTHENTICATED) @Produces(MediaType.TEXT_PLAIN) public String hello(Principal principal) { return "Hello, " + principal.getName() + "!"; }}

The@Controllermegjegyzés jelzi Micronautnak, hogy ez az összetevő kéréseket fog kapni a/hello útvonal.

az osztálynak csak egy módszere van: hello(). A @Get annotáció azt mutatja, hogy a módszer HTTP GET kéréseket kap. @Produces szükséges, mivel a Micronaut alapértelmezett visszatérési típusa JSON objektum. Mivel egyszerű szöveget küld vissza, ezt az információt kifejezetten meg kell határoznia a módszerben.

az utolsó megjegyzés: @Secured. Egyszerűen azt mondja Micronaut, hogy ez a módszer csak hitelesített felhasználók számára érhető el.

most már van egy vezérlő, amely biztosított, de még nem határozta meg a biztonsági konfigurációt. Állítsuk be a Micronaut-ot az Okta alkalmazáshoz való csatlakozáshoz.

nevezze át src/main/resources/application.ymlapplication.properties és adja hozzá a következő biztonsági konfigurációt:

micronaut.security.enabled=truemicronaut.security.token.jwt.enabled=truemicronaut.security.token.jwt.signatures.jwks.okta.url=https://{yourOktaDomain}/oauth2/default/v1/keys

cserélje ki a {yourOktaDomain} / div > az okta-fiókod értékével.

a fenti konfiguráció lehetővé teszi a biztonságot az OAuth 2.0 használatával. Ön kijelenti, hogy OAuth 2.0 ügyfele az Okta-ból származik, az Okta szervezet kibocsátójának megadásával.

Ön is engedélyezi a JSON Web tokenek vagy JWTs használatát. Mivel el szeretné olvasni az információkat az Okta-tól, be kell jelentenie, hogy hol találja meg a JWKS-t (JSON Web Key Set) a JWT aláírások érvényesítéséhez.

itt az ideje, hogy tesztelje a szolgáltatást! Indítsa el a kérelmet a végrehajtó a következő parancsot:

./mvnw mn:run

az alkalmazás fut, adjuk ki a következő parancsot:

curl -X GET -I http://localhost:8080/hello

A fenti parancsot készít eredmény hasonló:

HTTP/1.1 401 UnauthorizedDate: Tue, 8 Jan 2019 15:47:36 GMTtransfer-encoding: chunkedconnection: close

Mint látható, a kérelmet nem ment át. Ahhoz, hogy működjön, át kell adnia az OAuth 2.0 hozzáférési tokent, amelyet az OIDC hibakeresője kapott. Rendelje hozzá a hozzáférési tokent egyTOKEN változóhoz a héjban.

TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN...

hajtsa végre az alábbi parancsot:

curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/hello

most a várt módon működik! Ezúttal válaszként kapja meg az üdvözlő üzenetet:

láthatjuk, hogy a Micronaut nagyon kevés kódot igényel a biztonságos REST API létrehozásához. Ha megszámolta a kódsorokat, azt találta, hogy ~24% az XML (8 sor) függősége, a Java kód csak 22 sornyi kód, a biztonsági konfiguráció pedig 3 sort vesz igénybe. A Micronaut beépített OAuth 2.0 támogatása megkönnyíti az Okta-val való integrációt, sőt dokumentációjukban van egy útmutató az Okta-hoz.

nagyszerű! Most nézzük meg, hogyan hozhatja létre ugyanazt az alkalmazást a Quarkus használatával.

Készítsen Java REST API-t a Quarkus

használatával az alkalmazás fejlesztéséhez a Quarkus használatával csak a Maven telepítésre van szüksége, nincs szükség más függőségekre.

kezdjük el az alkalmazás létrehozását! Lépjen a létrehozni kívánt könyvtárba, majd hajtsa végre a következő parancsot:

mvn io.quarkus:quarkus-maven-plugin:1.8.1.Final:create \ -DprojectGroupId=com.okta.rest \ -DprojectArtifactId=quarkus \ -DclassName="com.okta.rest.quarkus.HelloResource" \ -Dpath="/hello" \ -Dextensions="jwt"

a fenti parancs létrehoz egy projektet a Quarkus Maven plugin segítségével. Létrehoz egy HelloResource nevű erőforrást, amely kéréseket fog kapni a /hello útvonalon. A Quarkus JWT kiterjesztését is hozzáadja a projekthez.

a projekt létrehozása után szerkessze a src/java/com/okta/rest/quarkus/HelloResource.java – ot, majd adja hozzá a felhasználói információkat a hello() metódushoz:

package com.okta.rest.quarkus;import io.quarkus.security.Authenticated;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.Produces;import javax.ws.rs.core.Context;import javax.ws.rs.core.MediaType;import javax.ws.rs.core.SecurityContext;import java.security.Principal;@Path("/hello")public class HelloResource { @GET @Path("/") @Authenticated @Produces(MediaType.TEXT_PLAIN) public String hello(@Context SecurityContext context) { Principal userPrincipal = context.getUserPrincipal(); return "Hello, " + userPrincipal.getName() + "!"; }}

a fenti osztály ugyanúgy viselkedik, mint a Micronaut-ban létrehozott osztály. Elolvassa a felhasználó adatait a kérésben generált token alapján, majd üdvözlő üzenetet küld a megtalált felhasználónak.

még mindig nem konfigurálta a Quarkus-t az Okta kibocsátójával és kulcsaival, tehát csináljuk.

Editsrc/main/resources/application.properties és adja hozzá a következő kódot:

mp.jwt.verify.publickey.location=https://{yourOktaDomain}/oauth2/default/v1/keysmp.jwt.verify.issuer=https://{yourOktaDomain}/oauth2/default

Kész! Az alkalmazás Quarkus verziója készen áll a tesztelésre. Menjen a projekt mappájába, és hajtsa végre a következő parancsot:

./mvnw compile quarkus:dev

a fenti parancs elindítja az alkalmazást.

az első lépés annak biztosítása, hogy megkapja a401 - Unauthorized, ha nem használja a megfelelő hitelesítő adatokat.

hajtsa végre a következő parancsot a terminálon:

curl -X GET -I http://localhost:8080/hello

az elvárásoknak megfelelően az eredmény egy HTTP 401 válasz:

HTTP/1.1 401 Unauthorizedwww-authenticate: Bearer {token}Content-Length: 0

Ha ugyanazt a kérést hajtja végre, beleértve az OIDC hibakereső tokenjét is, vissza kell adnia az üdvözlő üzenetet.

hajtsa végre a következő parancsot:

curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/hello

úgy működött, mint egy varázsa! Az én esetemben az eredmény:

a Quarkus még kevesebb kódsort igényel, mint a Micronaut! Generál egy app függőségek tartalmazza, 25 sor Java kódot, és csak 2 sor konfiguráció. Igen, a kódsorok buta összehasonlítás, de azt is megmutatja, hogy ezeknek a keretrendszereknek nagyon kevés kódra van szükségük a biztonságos alkalmazások fejlesztéséhez.

két lefelé, egy menni! Most, hogy sikerült megvalósítani az alkalmazást Micronaut és Quarkus, nézzük befejezni létrehozásával ugyanazt az alkalmazást a Spring Boot.

készítsen egy Java REST API-t a Spring Boot

A Spring Boot-nak nincsenek előfeltételei az alkalmazás létrehozásának megkezdéséhez, Tehát kezdjük a projekt létrehozásával!

nyissa meg a terminált, majd hajtsa végre a következő parancsot:

curl https://start.spring.io/starter.zip -d language=java \ -d bootVersion=2.3.4.RELEASE \ -d dependencies=web,okta \ -d packageName=com.okta.rest \ -d name=spring-boot \ -d type=maven-project \ -o spring-boot.zip

a fenti parancs létrehoz egyspring-boot.zip fájlt egy tavaszi rendszerindító alkalmazással, amely Maven-t használ. A fájlt az alábbi parancs segítségével kibonthatja egy spring-boot könyvtárba.

unzip spring-boot.zip -d spring-boot

most végrehajtja a kéréseket fogadó vezérlőt.

Hozzon létre egycom.okta.rest.controller csomagot és egy HelloController osztályt:

package com.okta.rest.controller;import org.springframework.security.core.annotation.AuthenticationPrincipal;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.security.Principal;@RestControllerpublic class HelloController { @GetMapping("/hello") public String hello(@AuthenticationPrincipal Principal principal) { return "Hello, " + principal.getName() + "!"; }}

a konfiguráció itt nagyon hasonlít a többi keretrendszerhez. Annotálja az osztályt @RestController hogy Spring tudja, hogy kéréseket fog kapni az osztályban. @GetMappingkap HTTP GET kéréseket a /hello útvonal. A Hitelesített felhasználó letöltéséhez használja a @AuthenticationPrincipal annotációt.

a többi keretrendszertől eltérően nem kell megadnia, hogy ez a végpont hitelesítve van, mivel a Spring már szabályozza ezt az információt a konfigurációiból.

az utolsó lépés a kibocsátó adatainak hozzáadása, így a Spring Security OIDC támogatása automatikusan felfedezheti azokat a végpontokat, amelyekkel kommunikálni kell.

Edit src/main/resources/applications.properties és adja hozzá a következő konfigurációt:

okta.oauth2.issuer=https://{yourOktaDomain}/oauth2/default

teszteljük! Indítsa el a tavaszi rendszerindító alkalmazást a Maven használatával.

./mvnw spring-boot:run

Akkor nyiss egy terminált, majd hajtsa végre a parancsot az alábbi:

curl -X GET -I http://localhost:8080/hello

A válasz HTTP 401 hiba, mivel nem tartalmazza a token:

HTTP/1.1 401Set-Cookie: JSESSIONID=316DCFD55C302A8D69EFD865411DFA77; Path=/; HttpOnlyWWW-Authenticate: BearerX-Content-Type-Options: nosniffX-XSS-Protection: 1; mode=blockCache-Control: no-cache, no-store, max-age=0, must-revalidatePragma: no-cacheExpires: 0X-Frame-Options: DENYContent-Length: 0Date: Thu, 09 Jan 2020 15:46:34 GMT

Teszt újra, most halad a token:

curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/hello

működött! A többi szolgáltatáshoz hasonlóan ennek a parancsnak az eredménye a következő:

tavaszi rendszerindító órák legalább a szükséges kódmennyiségben: 17 sor Java csak 1 sor konfiguráció! A tavasz mindig is kiváló volt a fejlesztők életének megkönnyítésében, így ez nem meglepő.

ennyi! Végre egy alapvető Java REST API mindhárom keretek!

Final Thoughts on REST API With Java: Micronaut, Quarkus, and Spring Boot

amikor a REST API fejlesztéséről van szó, mindhárom keretrendszer jól végezte a munkát. Csak egy kis kód és néhány konfiguráció, akkor képes volt arra, hogy dolgozzon ki egy biztonságos alkalmazás segítségével Okta és OAuth 2.0.

A tavasz már évek óta létezik, széles körben népszerű, számos jellemzője van az ökoszisztéma körül. Személy szerint még mindig úgy gondolom,hogy ez a legjobb megoldás a Java programozásakor.

a Micronaut és a Quarkus egyre népszerűbbé és lendületesebbé válik a Java közösségben. Ha szembe teljesítmény problémák, vagy talán ha fáj a változás, lehet, hogy egyikük egy próbát, hogy hogyan megy.

A teljesítmény a leggyakrabban kiemelt összehasonlító pont e három keret között. Ha keres gyors indítás egy szerver nélküli környezetben, vagy a képesség, hogy natív képek GraalVM, Micronaut és Quarkus valószínűleg jól működik az Ön számára. Csak szórakozásból, az egyes alkalmazások indítási ideje a következő (átlagosan három kísérlet alapján):

  • Micronaut: 474ms
  • Quarkus: 1132ms
  • tavaszi indítás: 1014ms

ezeket a számokat az egyes keretrendszerek Maven fejlesztési céljainak futtatásából kaptam.

  • Micronaut: ./mvnw mn:run
  • Quarkus: ./mvnw compile quarkus:dev
  • : ./mvnw spring-boot:run

ezek a parancsok nem optimalizáltak a sebességre, ezért minden egyes alkalmazást ./mvnw packagejava -jar – val indítottam.

  • Micronaut: 596ms
  • Quarkus: 658ms
  • tavaszi Boot: 1878ms

megjegyzés: ezeket a számokat egy 2019-es MacBook Pro-ra számították, 2,4 GHz-es, 8 magos Intel Core i9 processzorral és 64 GB RAM-mal. Az OpenJDK 15-öt nem használták JAVA_OPTS beállítással.

Ha még gyorsabb indítási időket keres, használhatja a GraalVM-et. Ahelyett, hogy magam futtattam volna az időzítési teszteket, megnéztem az egyes projektek dokumentációját.

  • Micronaut: 12ms az első Mikronaut Graal alkalmazás létrehozása szerint.
  • Quarkus: 14ms a Quarkus és a GraalVM szerint: hibernálás indítása szuperszonikus sebességgel, szubatomi méret az InfoQ-on. A Quarkus docs nem sorolja fel az indítási időt.
  • Spring Boot: 44ms szerint Spring Graal natív 0.6.0 megjelent.

a végén, akkor képes lesz arra, hogy produktív módon dolgozzon ki egy biztonságos alkalmazás, függetlenül attól, hogy a választás.

szeretné megnézni a forráskódot? Megtalálható a GitHub az okta-java-rest-api-összehasonlítás-példa.

szeretne többet megtudni a Java-ról, a REST API-król és a secure alkalmazásokról? Itt van néhány más hozzászólás a blogunkból, hogy hasznos lehet:

  • Watch GraalVM kapcsolja be a Java Binaries
  • OAuth 2.0 Java Guide: biztonságos az alkalmazás 5 perc
  • Java Microservices tavaszi Boot és Spring Cloud
  • hogyan lehet fejleszteni a Quarkus App Java és OIDC hitelesítés
  • egyszerű hitelesítés tavaszi biztonsági

több hozzászólás, mint ez, kövesse @oktadev a Twitteren. Mi is rendszeresen közzéteszi screencasts a YouTube-csatorna!

Changelog:

  • 2020. szeptember 23.: Micronaut 2.0.2, Quarkus 1.8.1, and Spring Boot 2.3.4. Lásd a Kódváltozásokat a GitHub példaalkalmazásában. Változások ezt a bejegyzést lehet megtekinteni oktadeveloper / okta-blog#423.
  • 2020. május 21. : hozzáadott indítási idők a java -jar számára, valamint a GraalVM használatával. Változások ezt a cikket lehet megtekinteni oktadeveloper / okta-blog#304.
  • 2020. május 20.: Micronaut 1.3.5-re, Quarkus 1.4.2-re és Spring Boot 2.3.0-ra frissítve. Lásd a Kódváltozásokat a GitHub példaalkalmazásában. Változások ezt a cikket lehet megtekinteni oktadeveloper / okta-blog#301.
  • 2020. Január 30.: Frissítve a Micronaut optimalizálására a Micronaut csapat visszajelzései alapján. Szintén újra számított indítási idők alapján átlagosan három kísérlet. Lásd a Kódváltozásokat a GitHub példaalkalmazásában. Változások ezt a cikket lehet megtekinteni oktadeveloper / okta-blog#176.

Related Posts

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük