使用 MSAL4J 搭配 Azure Active Directory B2C 啟用 Java Tomcat 應用程式的登入
本文示範 Java Tomcat 應用程式,其會使用適用於 Java 的 Microsoft 驗證連結庫來驗證 Azure Active Directory B2C (Azure AD B2C) 的使用者。
下圖顯示應用程式的拓撲:
應用程式會使用 MSAL4J 來登入使用者,並從 Azure AD B2C 取得標識碼 令牌 。 標識元令牌會證明用戶已針對 Azure AD B2C 租用戶進行驗證。
必要條件
- JDK 第 8 版或更高版本
- Maven 3
- Azure AD B2C 租使用者。 如需詳細資訊,請參閱 教學課程:建立 Azure Active Directory B2C 租使用者
- Azure AD B2C 租使用者中的用戶帳戶。
建議
- 一些熟悉 Java/Jakarta Servlets。
- 一些熟悉 Linux/OSX 終端機。
- jwt.ms 檢查令牌。
- Fiddler 用於監視您的網路活動和疑難解答。
- 請遵循Microsoft Entra ID 部落格,隨時掌握最新的發展。
設定範例
下列各節說明如何設定範例應用程式。
複製或下載範例存放庫
若要複製範例,請開啟Bash視窗,並使用下列命令:
git clone https://github.com/Azure-Samples/ms-identity-msal-java-samples.git
cd 3-java-servlet-web-app/1-Authentication/sign-in-b2c
或者,流覽至 ms-identity-msal-java-samples 存放庫,然後將它下載為 .zip 檔案,並將其解壓縮至您的硬碟。
重要
若要避免 Windows 上的檔案路徑長度限制,請將存放庫複製到硬碟根目錄附近的目錄中。
向 Azure AD B2C 租用戶註冊範例應用程式
此範例隨附預先註冊的應用程式以供測試之用。 如果您想要使用自己的 Azure AD B2C 租使用者和應用程式,請遵循下列各節中的步驟,在 Azure 入口網站 中註冊和設定應用程式。 否則,請繼續進行執行範例的步驟。
選擇您想要在其中建立應用程式的 Azure AD B2C 租使用者
若要選擇您的租使用者,請使用下列步驟:
登入 Azure 入口網站。
如果您的帳戶存在於多個 Azure AD B2C 租使用者中,請在 Azure 入口網站 的角落選取您的配置檔,然後選取 [切換目錄] 將會話變更為所需的 Azure AD B2C 租使用者。
建立使用者流程和自定義原則
若要建立常見的使用者流程,例如註冊、登入、配置檔編輯和密碼重設,請參閱 教學課程:在 Azure Active Directory B2C 中建立使用者流程。
您也應該考慮在 Azure Active Directory B2C 中建立自定義原則,不過,這已超出本教學課程的範圍。
新增外部識別提供者
請參閱 教學課程:在 Azure Active Directory B2C 中將識別提供者新增至您的應用程式。
註冊應用程式 (ms-identity-b2c-java-servlet-webapp-authentication)
若要註冊應用程式,請使用下列步驟:
流覽至 Azure 入口網站,然後選取 [Azure AD B2C]。
在瀏覽窗格中選取 [應用程式註冊 ],然後選取 [ 新增註冊]。
在出現的 [ 註冊應用程式] 頁面中 ,輸入下列應用程式註冊資訊:
- 在 [ 名稱] 區段中,輸入有意義的應用程式名稱,以顯示給應用程式的使用者 ,例如
ms-identity-b2c-java-servlet-webapp-authentication
。 - 在 [支援的帳戶類型] 底下,選取 [任何組織目錄中的帳戶和個人Microsoft帳戶(例如Skype、Xbox、Outlook.com)。
- 在 [ 重新導向 URI (選擇性)] 區段中,選取 下拉式方塊中的 [Web ],然後輸入下列重新導向 URI:
http://localhost:8080/ms-identity-b2c-java-servlet-webapp-authentication/auth_redirect
。
- 在 [ 名稱] 區段中,輸入有意義的應用程式名稱,以顯示給應用程式的使用者 ,例如
選取 [暫存器] 以建立應用程式。
在應用程式的註冊頁面上,尋找並複製 應用程式 (用戶端) 識別碼 值,以供稍後使用。 您會在應用程式的組態檔或檔案中使用此值。
選取儲存以儲存變更。
在應用程式的註冊頁面上,選取 瀏覽窗格中的 [憑證和秘密 ],以開啟您可以產生秘密並上傳憑證的頁面。
在用戶端密碼區段底下,選取新增用戶端密碼。
輸入描述 - 例如, 應用程式秘密。
選取其中一個可用的持續時間: 在1年、 2年內或 永不過期。
選取 [新增]。 產生的值隨即顯示。
複製並儲存產生的值,以供後續步驟使用。 您需要此值才能用於程式代碼的組態檔。 此值不會再次顯示,而且您無法透過任何其他方式加以擷取。 因此,請務必先從 Azure 入口網站 儲存它,再流覽至任何其他畫面或窗格。
設定應用程式 (ms-identity-b2c-java-servlet-webapp-authentication) 以使用您的應用程式註冊
使用下列步驟來設定應用程式:
注意
在下列步驟中,ClientID
與 或 AppId
相同Application ID
。
在 IDE 中開啟專案。
開啟 ./src/main/resources/authentication.properties 檔案。
尋找 屬性,
aad.clientId
並將現有值取代為應用程式標識碼或clientId
ms-identity-b2c-java-servlet-webapp-authentication
應用程式 Azure 入口網站。尋找 屬性,
aad.secret
並將現有的值取代為您在從 Azure 入口網站 建立ms-identity-b2c-java-servlet-webapp-authentication
應用程式期間儲存的值。尋找 屬性,
aad.scopes
並將現有的應用程式 clientId 取代為您在本節的步驟 1 中放入aad.clientId
的值。尋找 屬性,
aad.authority
並將 的第一個實例fabrikamb2c
取代為您在 Azure 入口網站 中建立ms-identity-b2c-java-servlet-webapp-authentication
應用程式的 Azure AD B2C 租用戶名稱。尋找 屬性,
aad.authority
並將的第二個實例fabrikamb2c
取代為您在 Azure 入口網站 中建立ms-identity-b2c-java-servlet-webapp-authentication
應用程式的 Azure AD B2C 租用戶名稱。aad.signInPolicy
尋找 屬性,並將它取代為您在 azure AD B2C 租使用者中建立的註冊/登入使用者流程原則名稱,您在其中在 Azure 入口網站 中建立ms-identity-b2c-java-servlet-webapp-authentication
應用程式。aad.passwordResetPolicy
尋找 屬性,並將它取代為您在 azure AD B2C 租使用者中建立的應用程式在 Azure 入口網站 中建立ms-identity-b2c-java-servlet-webapp-authentication
之密碼重設使用者流程原則的名稱。aad.editProfilePolicy
尋找 屬性,並將它取代為您在 azure AD B2C 租使用者中建立的編輯配置檔使用者流程原則名稱,您在 Azure 入口網站 中建立ms-identity-b2c-java-servlet-webapp-authentication
應用程式。
建置範例
若要使用 Maven 建置範例,請流覽至包含 範例pom.xml 檔案的目錄,然後執行下列命令:
mvn clean package
此命令會產生 您可以在各種應用程式伺服器上執行的 .war 檔案。
執行範例
下列各節說明如何將範例部署至 Azure App 服務。
必要條件
適用於 Azure App 服務 應用程式的 Maven 外掛程式
如果 Maven 不是您慣用的開發工具,請參閱下列使用其他工具的類似教學課程:
設定 Maven 外掛程式
當您部署至 Azure App 服務 時,部署會自動使用 Azure CLI 中的 Azure 認證。 如果 Azure CLI 未安裝在本機,則 Maven 外掛程式會使用 OAuth 或裝置登入進行驗證。 如需詳細資訊,請參閱使用 Maven 外掛程式進行驗證。
使用下列步驟來設定外掛程式:
執行下列命令來設定部署。 此命令可協助您設定 Azure App 服務 操作系統、Java 版本和 Tomcat 版本。
mvn com.microsoft.azure:azure-webapp-maven-plugin:2.13.0:config
針對 [ 建立新的執行組態],按 Y,然後按 Enter。
針對 [定義 OS 的值],針對 Windows 按 1,或針對 Linux 按 2,然後按 Enter。
針對 [ 定義 javaVersion 的值],按 2 for Java 11,然後按 Enter。
針對 [ 定義 webContainer 的值],按 4 for Tomcat 9.0,然後按 Enter。
針對 [ 定義 pricingTier 的值],按 Enter 以選取預設 P1v2 層。
針對 [確認],按 Y,然後按 Enter。
下列範例顯示部署程式的輸出:
Please confirm webapp properties
AppName : msal4j-servlet-auth-1707209552268
ResourceGroup : msal4j-servlet-auth-1707209552268-rg
Region : centralus
PricingTier : P1v2
OS : Linux
Java Version: Java 11
Web server stack: Tomcat 9.0
Deploy to slot : false
Confirm (Y/N) [Y]: [INFO] Saving configuration to pom.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 37.112 s
[INFO] Finished at: 2024-02-06T08:53:02Z
[INFO] ------------------------------------------------------------------------
確認您的選擇之後,外掛程式會將必要的外掛程式元素和設定新增至專案的pom.xml檔案,以將您的應用程式設定為在 Azure App 服務 中執行。
pom.xml檔案的相關部分看起來應該類似下列範例:
<build>
<plugins>
<plugin>
<groupId>com.microsoft.azure</groupId>
<artifactId>>azure-webapp-maven-plugin</artifactId>
<version>x.xx.x</version>
<configuration>
<schemaVersion>v2</schemaVersion>
<resourceGroup>your-resourcegroup-name</resourceGroup>
<appName>your-app-name</appName>
...
</configuration>
</plugin>
</plugins>
</build>
您可以直接在pom.xml中修改 App Service 的設定。 下表列出一些常見的設定:
屬性 | 必要 | 描述 |
---|---|---|
subscriptionId |
false | 訂用帳戶標識碼。 |
resourceGroup |
true | 應用程式的 Azure 資源群組。 |
appName |
true | 應用程式的名稱。 |
region |
false | 裝載您應用程式的區域。 預設值是 centralus 。 如需有效的區域,請參閱 支援的區域。 |
pricingTier |
false | 應用程式的定價層。 預設值是 P1v2 生產工作負載。 Java 開發和測試的建議最小值為 B2 。 如需詳細資訊,請參閱 App Service定價。 |
runtime |
false | 執行時間環境設定。 如需詳細資訊,請參閱設定詳細資料。 |
deployment |
false | 部署設定。 如需詳細資訊,請參閱設定詳細資料。 |
如需設定的完整清單,請參閱外掛程式參考文件。 所有 Azure Maven 外掛程式都會共用一組常見的組態。 如需這些組態,請參閱 一般組態。 如需 Azure App 服務 特定的設定,請參閱 Azure 應用程式:設定詳細數據。
請務必保留 appName
和 resourceGroup
值,以供日後使用。
準備應用程式以進行部署
當您將應用程式部署至 App Service 時,重新導向 URL 會變更為已部署應用程式實例的重新導向 URL。 使用下列步驟來變更屬性檔案中的這些設定:
流覽至應用程式的 authentication.properties 檔案,並將 的值
app.homePage
變更為已部署應用程式的功能變數名稱,如下列範例所示。 例如,如果您在上一個步驟中為應用程式名稱選擇example-domain
,您現在https://example-domain.azurewebsites.net
必須使用 此值app.homePage
。 請確定您也已將通訊協定從http
變更為https
。# app.homePage is by default set to dev server address and app context path on the server # for apps deployed to azure, use https://your-sub-domain.azurewebsites.net app.homePage=https://<your-app-name>.azurewebsites.net
儲存此檔案之後,請使用下列命令重建您的應用程式:
mvn clean package
重要
在這個相同的 authentication.properties 檔案中,您有 一個 設定。aad.secret
將此值部署至 App Service 不是很好的做法。 在程序代碼中保留此值並可能將其推送至 Git 存放庫,這兩者都不是很好的做法。 若要從程式代碼中移除此秘密值,您可以在部署至 App Service - 移除秘密一節中找到更詳細的指引。 本指南會新增額外的步驟,將秘密值推送至 金鑰保存庫 並使用 金鑰保存庫 References。
更新您的 Microsoft Entra ID 應用程式註冊
由於將 URI 重新導向至已部署的應用程式變更為 Azure App 服務,因此您也需要變更 Microsoft Entra ID 應用程式註冊中的重新導向 URI。 請使用下列步驟來進行此變更:
流覽至 適用於開發人員的 Microsoft 身分識別平台 應用程式註冊 頁面。
使用搜尋方塊來搜尋您的應用程式註冊 ,例如
java-servlet-webapp-authentication
。選取應用程式名稱以開啟您的應用程式註冊。
從選單中選擇 驗證。
在 [Web - 重新導向 URI] 區段中,選取 [新增 URI]。
填寫應用程式的 URI,並附加
/auth/redirect
-例如https://<your-app-name>.azurewebsites.net/auth/redirect
。選取儲存。
部署應用程式
您現在已準備好將應用程式部署至 Azure App 服務。 使用下列命令,確定您已登入 Azure 環境以執行部署:
az login
在pom.xml檔案中備妥所有組態後,您現在可以使用下列命令將 Java 應用程式部署至 Azure:
mvn package azure-webapp:deploy
部署完成之後,您的應用程式即可在 就緒 http://<your-app-name>.azurewebsites.net/
。 使用本機網頁瀏覽器開啟 URL,您應該會在其中看到應用程式的起始頁面 msal4j-servlet-auth
。
探索範例
使用下列步驟來探索範例:
- 請注意畫面中央顯示的已登入或註銷狀態。
- 選取角落中的上下文相關按鈕。 當您第一次執行應用程式時,此按鈕會 讀取 [登入 ]。
- 在下一個頁面上,遵循指示,並使用所選身分識別提供者的帳戶登入。
- 請注意,上下文相關按鈕現在會顯示 [註銷 ] 並顯示您的用戶名稱。
- 選取 [ 標識符令牌詳細數據 ],以查看一些標識符令牌已譯碼的宣告。
- 您也可以選擇編輯設定檔。 選取連結以編輯詳細數據,例如您的顯示名稱、居住地和職業。
- 使用角落中的按鈕註銷。
- 註銷之後,流覽至令牌詳細數據頁面的下列 URL:
http://localhost:8080/ms-identity-b2c-java-servlet-webapp-authentication/auth_token_details
。 您可以在這裏觀察應用程式401: unauthorized
顯示錯誤的方式,而不是標識元令牌宣告。
關於程式碼
此範例示範如何使用 MSAL4J 將使用者登入您的 Azure AD B2C 租使用者。
目錄
下表顯示範例項目資料夾的內容:
檔案/資料夾 | 描述 |
---|---|
AuthHelper.java | 驗證的協助程式函式。 |
Config.java | 在啟動時執行,並設定屬性讀取器和記錄器。 |
authentication.properties | Microsoft Entra 識別碼和程序設定。 |
AuthenticationFilter.java | 將未經驗證的要求重新導向至受保護的資源至 401 頁面。 |
MsalAuthSession | 使用 HttpSession 具現化。 將所有 MSAL 相關的工作階段屬性儲存在工作階段屬性中。 |
____Servlet.java | 所有可用的端點都定義於以____Servlet.java結尾的類別.java類別中。 |
CHANGELOG.md | 範例的變更清單。 |
CONTRIBUTING.md | 參與範例的指導方針。 |
許可證 | 範例的授權。 |
ConfidentialClientApplication
ConfidentialClientApplication
實例會在 AuthHelper.java 檔案中建立,如下列範例所示。 此物件有助於製作 Azure AD B2C 授權 URL,並協助交換存取令牌的驗證令牌。
IClientSecret secret = ClientCredentialFactory.createFromSecret(SECRET);
confClientInstance = ConfidentialClientApplication
.builder(CLIENT_ID, secret)
.b2cAuthority(AUTHORITY + policy)
.build();
下列參數用於具現化:
- 應用程式的用戶端識別碼。
- 客戶端密碼,這是機密用戶端應用程式的需求。
- 與適當的
UserFlowPolicy
Azure AD B2C 授權單位串連,適用於註冊、登入、配置檔編輯或密碼重設。
在此範例中,這些值會使用 Config.java 檔案中的屬性讀取器,從 authentication.properties 檔案讀取。
逐步解說
下列步驟提供應用程式的功能的逐步解說:
登入程式的第一個步驟是將要求傳送至
/authorize
Azure Active Directory B2C 租使用者的端點。 MSAL4JConfidentialClientApplication
實例可用來建構授權要求 URL,而應用程式會將瀏覽器重新導向至此 URL,如下列範例所示:final ConfidentialClientApplication client = getConfidentialClientInstance(policy); final AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters .builder(REDIRECT_URI, Collections.singleton(SCOPES)).responseMode(ResponseMode.QUERY) .prompt(Prompt.SELECT_ACCOUNT).state(state).nonce(nonce).build(); final String redirectUrl = client.getAuthorizationRequestUrl(parameters).toString(); Config.logger.log(Level.INFO, "Redirecting user to {0}", redirectUrl); resp.setStatus(302); resp.sendRedirect(redirectUrl);
下列清單描述此程式碼的功能:
AuthorizationRequestUrlParameters
:必須設定的參數,才能建置 AuthorizationRequestUrl。REDIRECT_URI
:在收集使用者認證之後,Azure AD B2C 會重新導向瀏覽器以及驗證碼。SCOPES
: 範圍 是應用程式要求的許可權。一般而言,這三個範圍
openid profile offline_access
就足以接收標識符令牌回應。 不過,MSAL4J 要求來自 Azure AD B2C 的所有回應也包含存取令牌。為了讓 Azure AD B2C 分配存取令牌和標識碼令牌,要求必須包含額外的資源範圍。 因為此應用程式實際上不需要外部資源範圍,所以它會將自己的用戶端標識元新增為第四個範圍,以接收存取令牌。
您可以在 authentication.properties 檔案中找到應用程式所要求的範圍完整清單。
ResponseMode.QUERY
:Azure AD B2C 可以將響應當做 HTTP POST 要求中的表單參數傳回,或做為 HTTP GET 要求中的查詢字串參數。Prompt.SELECT_ACCOUNT
:Azure AD B2C 應該要求用戶選取他們打算驗證的帳戶。state
:應用程式在每個令牌要求上設定的唯一變數,並在收到對應的 Azure AD B2C 重新導向回呼之後終結。 狀態變數可確保對的 Azure AD B2C 要求/auth_redirect endpoint
實際上是來自此應用程式和此會話的 Azure AD B2C 授權要求,進而防止 CSRF 攻擊。 這會在 AADRedirectServlet.java 檔案中完成。nonce
:應用程式在每個令牌要求上設定為會話的唯一變數,並在收到對應的令牌之後終結。 此 Nonce 會轉譯為已分配 Azure AD B2C 的結果令牌,以確保不會發生令牌重新執行攻擊。
使用者會看到 Azure Active Directory B2C 的登入提示。 如果登入嘗試成功,則會將使用者的瀏覽器重新導向至應用程式的重新導向端點。 對這個端點的有效要求包含 授權碼。
然後,實例會
ConfidentialClientApplication
交換此授權碼,以取得來自 Azure Active Directory B2C 的標識元令牌和存取令牌,如下列範例所示:final AuthorizationCodeParameters authParams = AuthorizationCodeParameters .builder(authCode, new URI(REDIRECT_URI)) .scopes(Collections.singleton(SCOPES)).build(); final ConfidentialClientApplication client = AuthHelper .getConfidentialClientInstance(policy); final Future<IAuthenticationResult> future = client.acquireToken(authParams); final IAuthenticationResult result = future.get();
下列清單描述此程式碼的功能:
AuthorizationCodeParameters
:必須設定的參數,才能交換標識符和/或存取令牌的授權碼。authCode
:在重新導向端點收到的授權碼。REDIRECT_URI
:必須再次傳遞上一個步驟中使用的重新導向 URI。SCOPES
:必須再次傳遞上一個步驟中使用的範圍。
如果
acquireToken
成功,則會擷取令牌宣告,且 nonce 宣告會針對儲存在會話中的 nonce 進行驗證,如下列範例所示:parseJWTClaimsSetAndStoreResultInSession(msalAuth, result, serializedTokenCache); validateNonce(msalAuth) processSuccessfulAuthentication(msalAuth);
如果成功驗證 nonce,驗證狀態會放入伺服器端會話,並利用 類別所
MsalAuthSession
公開的方法,如下列範例所示:msalAuth.setAuthenticated(true); msalAuth.setUsername(msalAuth.getIdTokenClaims().get("name"));
其他相關資訊
- 什麼是 Azure Active Directory B2C?
- 可在 Active Directory B2C 中使用的應用程式類型
- Azure Active Directory B2C 的建議和最佳做法
- Azure AD B2C 工作階段
- 適用於 Java 的 Microsoft 驗證程式庫 (MSAL)
如需 OAuth 2.0 通訊協定在此案例和其他案例中運作方式的詳細資訊,請參閱 Microsoft Entra ID 的驗證案例。