使用Okta的单点登录保护您的Vert.x服务器
“我喜歡編寫身份驗(yàn)證和授權(quán)代碼。” ?從來(lái)沒(méi)有Java開(kāi)發(fā)人員。 厭倦了一次又一次地建立相同的登錄屏幕? 嘗試使用Okta API進(jìn)行托管身份驗(yàn)證,授權(quán)和多因素身份驗(yàn)證。
Vert.x是Spring生態(tài)系統(tǒng)中增長(zhǎng)最快的元素之一,保護(hù)Vert.x服務(wù)器可能是一個(gè)挑戰(zhàn)。 部署Okta可以讓您向服務(wù)器添加安全的單點(diǎn)登錄,同時(shí)還可以授予您訪問(wèn)有關(guān)用戶的大量信息的權(quán)限。 本教程將指導(dǎo)您站起一個(gè)新的Vert.x服務(wù)器,并將其與Okta集成以進(jìn)行安全的用戶管理。
三步OAuth流程快速回顧
此示例將使用稱為三足流(單點(diǎn)登錄的實(shí)質(zhì))的第三方提供程序OAuth流。 在開(kāi)始編寫代碼之前,簡(jiǎn)要回顧一下此過(guò)程可能會(huì)有所幫助。
問(wèn)題
我是Web服務(wù)器,我想保護(hù)我的網(wǎng)站并要求用戶登錄。但是,編寫,維護(hù)和管理用戶身份是很多工作。
解決方案
讓別人來(lái)處理它。 為此,我(Web服務(wù)器),我的用戶(可能在Web瀏覽器上)以及為我處理auth的人(在此示例中為Okta)之間需要一些合作。 這三個(gè)合作的參與者是三腿OAuth流的三個(gè)“腿”。 他們經(jīng)歷的過(guò)程是三向握手:
完成此示例后,上述握手將在幕后發(fā)生。 Vert.x提供了一個(gè)方便的OAuth庫(kù)來(lái)為您完成整個(gè)過(guò)程-您所需要做的就是對(duì)其進(jìn)行配置并進(jìn)行適當(dāng)?shù)淖?cè)。 這就是本教程演示的內(nèi)容。
作為入門指南,本文假定僅基本熟悉Java和一些Java要素,例如Maven。 如果您已經(jīng)在運(yùn)行Vert.x服務(wù)器,請(qǐng)隨時(shí)快速了解相關(guān)內(nèi)容:您將在“ 配置Vert.x OAuth處理程序”部分中與Okta集成。
完整的代碼示例(包括imports和pom.xml)可以在Github上找到。
啟動(dòng)新的Vert.x服務(wù)器
要開(kāi)始工作,請(qǐng)?jiān)L問(wèn)Vert.x Starter頁(yè)面并生成一個(gè)新項(xiàng)目。 對(duì)于本教程,您可以保留所有默認(rèn)值,并包括Vert.x Web , OAuth和Vert.x Config依賴項(xiàng):
單擊本地生成,下載和解壓縮后,您應(yīng)該看到以下簡(jiǎn)單目錄結(jié)構(gòu):
在demo目錄中使用mvn compile exec:java運(yùn)行時(shí),應(yīng)在端口8080上啟動(dòng)服務(wù)器:
在瀏覽器中訪問(wèn)http://localhost:8080將返回令人放心的hello world響應(yīng):
在這一點(diǎn)上,下一步是在繼續(xù)添加身份驗(yàn)證之前切換到https。 但是,為了使本教程簡(jiǎn)短而集中,將跳過(guò)該部分,并且示例將繼續(xù)使用未加密的http服務(wù)器模式。
引入Vert.x配置
Vert.x提供了一個(gè)通用的配置庫(kù),盡管要比Spring設(shè)置更多的工作。 本示例將使用一些配置值,因此您可以借此機(jī)會(huì)將Vert.x Config添加到項(xiàng)目中。 如果在創(chuàng)建啟動(dòng)程序項(xiàng)目時(shí)指定了Vert.x Config,則該依賴項(xiàng)應(yīng)該已經(jīng)存在于pom.xml 。
<dependency><groupId>io.vertx</groupId><artifactId>vertx-config</artifactId><version>${vertx.version}</version> </dependency>創(chuàng)建一個(gè)名為src/main/application.json的文件,并添加以下內(nèi)容:
{"clientId": "{okta-client-id}","clientSecret": "{okta-client-secret}","issuer": "https://{yourOktaDomain}/oauth2/default","callbackUrl": "http://localhost:8080/login","port": 8080 }您將很快更新這些值。 現(xiàn)在,在src/main/java/com/example/demo/MainVerticle.java ,將start()方法的內(nèi)容替換為以下內(nèi)容,這將加載配置。 請(qǐng)注意,完成后,它將調(diào)用一個(gè)尚不存在的名為startServer()的方法。 您將在下一節(jié)中添加它。
@Override public void start() throws Exception {ConfigStoreOptions fileStore = new ConfigStoreOptions().setType("file").setConfig(new JsonObject().put("path", "src/main/application.json"));ConfigRetrieverOptions options = new ConfigRetrieverOptions().addStore(fileStore);ConfigRetriever retriever = ConfigRetriever.create(vertx, options);retriever.getConfig(ar -> {if (ar.failed()) {System.err.println("failed to retrieve config.");} else {config().mergeIn(ar.result());startServer();}}); }整合Vert.x路由器
通過(guò)使用Vert.x路由器 ,您將能夠輕松攔截對(duì)敏感端點(diǎn)的呼叫并強(qiáng)制進(jìn)行預(yù)身份驗(yàn)證。 為此,您現(xiàn)在將在src/main/java/com/example/demo/MainVerticle.java實(shí)現(xiàn)startServer()方法:
void startServer() {Router router = Router.router(vertx);router.route("/private/secret").handler(ctx -> {ctx.response().end("Hi");});vertx.createHttpServer().requestHandler(router::accept).listen(config().getInteger("port")); }在上面的示例中,您已經(jīng)在/private/secret創(chuàng)建了一個(gè)新端點(diǎn),目的是盡快保護(hù)/private路徑下的每個(gè)端點(diǎn)。 但首先,需要設(shè)置Vert.x OAuth處理程序。
創(chuàng)建Okta帳戶并收集憑據(jù)
如果您還沒(méi)有免費(fèi)的Okta帳戶,則可以按照以下說(shuō)明創(chuàng)建一個(gè)帳戶并設(shè)置您的第一個(gè)Okta應(yīng)用程序。 您需要收集四個(gè)關(guān)鍵信息:
- 客戶編號(hào)-例如: oot9wrjjararhfaa
- 客戶機(jī)密-(保持機(jī)密!)
- 發(fā)行者–例如: https : //dev-123123.oktapreview.com/oauth2/default…請(qǐng)確保包括/ oauth2 / default路徑!
- 回調(diào)網(wǎng)址-如果遵循上述說(shuō)明,則為http:// localhost:8080 / login 。
現(xiàn)在可以在src/main/application.json文件中使用這些值。
配置Vert.x OAuth處理程序
Vert.x帶有一個(gè)現(xiàn)成的OAuth管理器,可以與Okta作為身份提供者很好地集成在一起。 為了使內(nèi)容整潔,您將在src/main/java/com/example/demo/MainVerticle.java中創(chuàng)建一個(gè)單獨(dú)的工廠方法,該方法會(huì)生成已配置的OAuth處理程序。 將以下內(nèi)容添加到MainVerticle類中,將下面的客戶端信息替換為從Okta開(kāi)發(fā)人員儀表板獲得的帳戶詳細(xì)信息:
AuthHandler getOAuthHandler(Router router) {OAuth2Auth oauth2 = OAuth2Auth.create(vertx, OAuth2FlowType.AUTH_CODE, new OAuth2ClientOptions().setClientID(config().getString("clientId")).setClientSecret(config().getString("clientSecret")).setSite(config().getString("issuer")).setTokenPath("/v1/token").setAuthorizationPath("/v1/authorize").setUserInfoPath("/v1/userinfo").setUseBasicAuthorizationHeader(false));OAuth2AuthHandler authHandler = OAuth2AuthHandler.create(oauth2, config().getString("callbackUrl"));authHandler.extraParams(new JsonObject("{\"scope\":\"openid profile email\"}"));authHandler.setupCallback(router.route());return authHandler; }在上面的示例中,請(qǐng)注意三個(gè)請(qǐng)求的范圍: openid , profile和email 。 將來(lái)的帖子將探討其他范圍和授權(quán)級(jí)別,但是目前,這三個(gè)將提供絕對(duì)必要的條件(例如用戶名和電子郵件地址)。 使用電子郵件地址,您還可以直接查詢Okta的API以獲取有關(guān)用戶的其他信息,并執(zhí)行帳戶管理任務(wù)。
攔截并授權(quán)受保護(hù)的端點(diǎn)
現(xiàn)在已經(jīng)準(zhǔn)備好AuthHandler ,它需要在對(duì)任何受保護(hù)端點(diǎn)的請(qǐng)求處理之前并驗(yàn)證用戶身份。 通過(guò)使用通配符將其注冊(cè)為/private/下所有路徑的頂級(jí)處理程序,只需為您將來(lái)可能創(chuàng)建的所有處理程序處理一次即可。 然后可以保證/private/路徑下的任何請(qǐng)求處理程序都將確保,在調(diào)用該請(qǐng)求處理程序時(shí),它將僅來(lái)自經(jīng)過(guò)正確身份驗(yàn)證的用戶。
如下所示更改MainVerticle類的startServer()方法,以生成并注冊(cè)處理程序:
public void startServer() {Router router = Router.router(vertx);//create and register the auth handler to intercept all//requests below the /private/ URI:AuthHandler authHandler = getOAuthHandler(router);router.route("/private/*").handler(authHandler);router.route("/private/secret").handler(ctx -> {ctx.response().end("Hi");});vertx.createHttpServer().requestHandler(router::accept).listen(config().getString(“port”)); }這將是重新啟動(dòng)服務(wù)器并確保一切正常運(yùn)行的絕佳時(shí)機(jī)。 通過(guò)再次運(yùn)行mvn compile java:exec并從瀏覽器中訪問(wèn)http://localhost:8080/private/secret ,您現(xiàn)在應(yīng)該被自動(dòng)重定向到Okta的登錄頁(yè)面。 登錄后,應(yīng)將您重定向回您的站點(diǎn),以繼續(xù)響應(yīng)原始的/private/secret請(qǐng)求。
從JWT提取用戶信息
現(xiàn)在,您的/private/ API的調(diào)用者已登錄,接下來(lái)您需要的是他們的信息。 它以JSON Web令牌的形式提供,必須將其提取并解碼。 Vert.x OAuth處理程序?qū)⑵潆[藏為名為Principal的字符串化JSON對(duì)象的命名成員,該對(duì)象本身是上下文用戶對(duì)象的組成部分。 然后使用您選擇的JWT庫(kù)對(duì)該編碼的令牌進(jìn)行解碼和驗(yàn)證。 本示例使用Okta的JWT驗(yàn)證程序庫(kù) 。
access_token和id_token均可用,但是本教程將僅解碼id_token 。 如果需要,還有一個(gè)類似的函數(shù)可以對(duì)access_token進(jìn)行解碼。 為此,請(qǐng)?jiān)趐om.xml包含Okta JWT lib依賴項(xiàng):
<dependency><groupId>com.okta.jwt</groupId><artifactId>okta-jwt-verifier</artifactId><version>0.2.0</version> </dependency>…并將以下新函數(shù)添加到MainVertical類中:
Map<String, Object> getIdClaims(RoutingContext ctx) {try {JwtVerifier jwtVerifier = new JwtHelper().setIssuerUrl(config().getString(“issuer”)).setAudience("api://default").setClientId(config().getString("clientId")).build();Jwt idTokenJwt = jwtVerifier.decodeIdToken(ctx.user().principal().getString("id_token"), null);return idTokenJwt.getClaims();} catch (Exception e) {//do something with the exception...return new HashMap<>();} }就是這樣! 現(xiàn)在,您可以在請(qǐng)求處理程序中訪問(wèn)用戶信息。 為了演示,可以對(duì)/private/secret處理程序進(jìn)行更新以從JWT檢索聲明,如下所示:
void startServer() {Router router = Router.router(vertx);AuthHandler authHandler = getOAuthHandler(router);router.route("/private/*").handler(authHandler);router.route("/private/secret").handler(ctx -> {Map claims = getIdClaims(ctx);ctx.response().end("Hi " +claims.get("name") +", the email address we have on file for you is: "+claims.get("email"));});vertx.createHttpServer().requestHandler(router::accept).listen(config().getString(“port”)); }經(jīng)過(guò)最后的更改,重新啟動(dòng)服務(wù)器并再次點(diǎn)擊http://localhost:8080/private/secret ,您的瀏覽器現(xiàn)在應(yīng)該顯示一條消息,其中包含您已通過(guò)身份驗(yàn)證的用戶信息!
步步高升
恭喜,您現(xiàn)在擁有一臺(tái)高性能的Vert.x服務(wù)器,受到Okta先進(jìn)的安全性和身份管理保護(hù)! Okta提供了Java SDK,用于進(jìn)一步與用戶和帳戶進(jìn)行交互,包括向用戶添加自定義數(shù)據(jù)和屬性。
感謝您的閱讀,并且一如既往,請(qǐng)?jiān)谙旅娴脑u(píng)論中向我們提問(wèn)。 我們希望您在Twitter @OktaDev上關(guān)注我們,或者從我們的博客中Java內(nèi)容:
- Spring Security 5.0和OIDC入門
- 使用Spring Boot和React進(jìn)行Bootiful開(kāi)發(fā)
- 使用Kong Gateway集中身份驗(yàn)證
- 使用Angular 5.0和Spring Boot 2.0構(gòu)建基本的CRUD應(yīng)用
- 使用Spring Boot和OAuth保護(hù)您的SPA
“我喜歡編寫身份驗(yàn)證和授權(quán)代碼。” ?從來(lái)沒(méi)有Java開(kāi)發(fā)人員。 厭倦了一次又一次地建立相同的登錄屏幕? 嘗試使用Okta API進(jìn)行托管身份驗(yàn)證,授權(quán)和多因素身份驗(yàn)證。
使用Okta將Single Sign-on添加到您的Vert.x Server最初于2018年1月11日發(fā)布在Okta開(kāi)發(fā)人員博客上。
翻譯自: https://www.javacodegeeks.com/2018/03/secure-vert-x-server-single-sign-okta.html
總結(jié)
以上是生活随笔為你收集整理的使用Okta的单点登录保护您的Vert.x服务器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 袁隗怎么读 袁隗的简介
- 下一篇: Apache Kafka简介