追蹤 Java 網頁應用程式登入流程
本攻略透過示範性的 Java servlet 程式碼追蹤登入請求。 它說明了瀏覽器、Microsoft Entra ID、MSAL4J 以及應用程式的會話輔助器如何互動。
Note
這些片段並非完整的應用程式或可生產環境的實作。 他們省略了周圍的 servlet 程式碼、匯入、設定和部分錯誤處理,專注於流程。 完成此單元不需要建置或執行任何應用程式。
識別應用程式定義的輔助工具
MSAL4J 提供代幣取得 API。 應用程式提供協調瀏覽器重定向、回調處理及會話的相關程式碼。 這些片段使用了以下說明輔助工具:
| 小幫手 | 在範例中的角色 |
|---|---|
Config |
提供應用程式設定。
REDIRECT_URI 代表已註冊的回呼 URI,而 SCOPES 則包含單一的 Microsoft Graph 權限範圍 User.Read。 |
getConfidentialClientInstance 與 AuthHelper.getConfidentialClientInstance |
回傳一個已設定好的 ConfidentialClientApplication。 |
contextAdapter |
將 HTTP 請求與回應連接到應用程式的會話上下文。 它的 redirectUser 方法會將瀏覽器重新導向。 |
IdentityContextData 與 context |
儲存與登入要求和工作階段相關的資料,包括 nonce、權杖宣告、驗證結果,以及序列化的權杖快取。 |
這些名稱及其輔助方法是應用程式定義的,而非 MSAL4J API。 他們的角色在攻略中有說明,但沒有包含他們的實作。
授權網址啟動瀏覽器互動
第一個片段展示應用程式如何建立授權網址並重新導向瀏覽器。 助手提供一個已設定的機密客戶端。 應用程式也為此登入請求產生了新的、不可預測的 state 和 nonce 值,並保留這些值以供後續比較。
final ConfidentialClientApplication client = getConfidentialClientInstance();
AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters
.builder(Config.REDIRECT_URI, Collections.singleton(Config.SCOPES))
.responseMode(ResponseMode.QUERY)
.prompt(Prompt.SELECT_ACCOUNT)
.state(state)
.nonce(nonce)
.build();
final String authorizeUrl = client.getAuthorizationRequestUrl(parameters).toString();
contextAdapter.redirectUser(authorizeUrl);
AuthorizationRequestUrlParameters 描述回調 URI、請求範圍及協定選項。
Collections.singleton 此處適用,因為 Config.SCOPES 包含一個作用域,而非多個範圍的空間分離清單。 MSAL 預設新增了標準的 OpenID Connect 範圍 openid、 profile、 offline_access 。
在 MSAL4J 1.9.1 版本中,授權 ResponseMode.QUERY 回應參數會放在回調的查詢字串中。
Prompt.SELECT_ACCOUNT 請求帳戶選擇。
state 幫助將回應與登入請求相關聯,同時 nonce 將 ID 標記綁定到該請求。
Note
從 MSAL4J 1.24.0 開始, ResponseMode.QUERY 已被棄用。 當傳遞此值時, AuthorizationRequestUrlParameters.Builder.responseMode 會 ResponseMode.FORM_POST 替換並記錄警告。 這是函式庫的行為改變;Microsoft Entra 仍支援協定層級的查詢模式授權碼回應。
對於表單 POST 回應,servlet 回呼需要可處理 POST 的機制,例如 doPost,而不是僅依賴 doGet。 回調處理仍必須保留相關的會話、 statenonce 驗證與錯誤處理。 僅變更回應模式 enum,並無法解決這些職責。
getAuthorizationRequestUrl 建構網址; redirectUser 是應用程式定義的輔助工具,負責重新導向瀏覽器。 這兩種操作都不會兌換授權碼。
Important
圖中所示的要求在登入期間包含委派的 Microsoft Graph User.Read。 同意提示僅在需要同意且租戶政策允許使用者授予同意時出現;事先使用者或管理員同意可能導致沒有提示出現。 需要 管理員批准 訊息表示授權管理員必須透過組織核准流程審查申請。 適當的回應不是削弱全租戶的同意政策。 請參閱 使用者與管理員同意條款。
回撥會將授權碼交換為權杖
在成功授權回應後,Microsoft Entra ID 會將瀏覽器以授權碼重新導向到應用程式的回調 URI。 以下片段聚焦於在回調驗證 state、處理錯誤回應並提取 authCode後的贖回。 它沒有顯示完整的回撥實作。
final AuthorizationCodeParameters authParams = AuthorizationCodeParameters
.builder(authCode, new URI(Config.REDIRECT_URI))
.scopes(Collections.singleton(Config.SCOPES))
.build();
final ConfidentialClientApplication client = AuthHelper.getConfidentialClientInstance();
final IAuthenticationResult result = client.acquireToken(authParams).get();
AuthorizationCodeParameters 將接收的程式碼連接到回調 URI 及請求的範圍。 重定向 URI 必須與授權請求及應用程式註冊時使用的 URI 相符。 機密用戶端在憑證端點交換程式碼時,負責驗證應用程式。
acquireToken 回傳一個未來,並 .get() 在此範例中等待其結果。 成功兌換會產生 IAuthenticationResult;兌換失敗必須作為錯誤處理。 授權碼是短時間且一次性使用的憑證,無法用於後續的 API 呼叫。
Note
對於新實作,請遵循現行授權碼流程指引:Microsoft 建議所有應用程式類型(包括機密網頁應用程式)使用 Proof Key for Code Exchange(PKCE)。 PKCE 是單頁應用程式(SPA)的必要條件,但並非此處所示機密網頁應用程式的平台要求。
此處顯示的明確 MSAL4J URL 建構與代碼兌換 API 不會自動產生 PKCE 輸入。 為每個登入請求產生一個全新且不可預測的驗證器,並安全保存以供匹配回撥使用。 在授權請求建構器上,提供其 S256 衍生的挑戰作為 codeChallenge,並設定 codeChallengeMethod("S256");在兌換建構器上,提供對應的 codeVerifier。 PKCE 並不能取代用戶端的認證或statenonce驗證。 上述片段省略了這些 PKCE 輸入。
應用程式會將結果與會話關聯起來
下一個片段說明接收權杖與將工作階段視為已通過驗證之間的界線。 這裡, context 是一個應用程式定義 IdentityContextData 的實例。
context.setIdTokenClaims(result.idToken());
validateNonce(context);
context.setAuthResult(result, client.tokenCache().serialize());
第一次呼叫會使 ID 權杖宣告可供應用程式的 nonce 驗證使用。 應用程式定義 validateNonce 的輔助工具會將回傳的 nonce 與原始請求保留的值比較,若驗證失敗則停止處理。 最後的呼叫會在應用程式內容中記錄驗證結果與序列化權杖快取,周邊程式碼會將其與工作階段建立關聯。
這些輔助工具並不會取代應用程式更廣泛的安全責任。 完整的實作還需要正確的回應處理、安全的會話與標記快取儲存、適當的錯誤處理,以及對受保護操作的授權。
連接流程
瀏覽器會帶著使用者登入並回傳授權碼。 伺服器會用 MSAL4J 換值該程式碼,處理結果並維護應用程式的會話。 後續的 Microsoft Graph 呼叫則使用存取權杖,而非授權碼或 ID 權杖。
欲了解更多關於函式庫 API 的資訊,請參閱 MSAL4J 授權碼 URL 建置 器及 Acquire token with authorization code。