使用 Azure Active Directory B2C 將登入新增至 Spring Web 應用程式

本文說明如何使用 Spring Initializr 搭配適用於 Microsoft Entra ID 的 Spring Boot Starter,建立具有登入功能的 Java 應用程式。

在本教學課程中,您會了解如何:

  • 使用 Spring Initializr 建立 Java 應用程式
  • 設定 Azure Active Directory B2C
  • 使用 Spring Boot 類別和批註保護應用程式
  • 建置及測試Java應用程式

Microsoft Entra ID 是 Microsoft 的雲端規模企業身分識別解決方案。 Azure Active Directory B2C 可補充 Microsoft Entra ID 的功能集,讓您管理客戶、取用者和公民存取您企業對消費者 (B2C) 應用程式。

必要條件

重要

需要 Spring Boot 2.5 版或更高版本,才能完成本文中的步驟。

使用 Spring Initializr 建立應用程式

  1. 瀏覽至 https://start.spring.io/

  2. 根據本指引填寫值。 標籤和版面配置可能與此處顯示的影像不同。

    • 在 [專案] 底下,選取 [Maven 專案]。
    • 在 [語言] 底下,選取 [Java]。
    • 在 [Spring Boot] 底下,選取 [2.7.11]。
    • 在 [群組] 底下[成品] 和 [名稱] 會使用簡短的描述性字串來輸入相同的值。 當您輸入時,UI 可能會自動填入其中一些欄位。
    • 在 [ 相依性] 窗格中,選取 [ 新增相依性]。 使用 UI 在 Spring WebSpring Security 上新增相依性。

    注意

    Spring Security 5.5.1、5.4.7、5.3.10 和 5.2.11 已發行,以解決下列 CVE 報告 CVE-2021-22119:Spring-security-oauth2-client 的拒絕服務攻擊。 如果您使用舊版,請加以升級。

  3. 選取 [ 產生專案],然後將專案下載到本機計算機上的路徑。 將下載的檔案移至以專案命名的目錄,並將檔案解壓縮。 檔案設定看起來應該像下面這樣,而您針對 Group 輸入的值會取代 yourProject

    .
    ├── HELP.md
    ├── mvnw
    ├── mvnw.cmd
    ├── pom.xml
    └── src
        ├── main
        │   ├── java
        │   │   └── yourProject
        │   │       └── yourProject
        │   │           └── YourProjectApplication.java
        │   └── resources
        │       ├── application.properties
        │       ├── static
        │       └── templates
        └── test
            └── java
                └── yourProject
                    └── yourProject
                        └── YourProjectApplicationTests.java
    

建立和初始化 Microsoft Entra 實例

建立 Active Directory 實例

  1. https://portal.azure.com登入 。

  2. 選取 [建立資源]。 搜尋 Azure Active Directory B2C

    使用 Azure 入口網站 建立新的 Azure Active Directory B2C 實例。

  3. 選取 建立

    Azure Active Directory B2C 的 Azure Marketplace 專案。

  4. 選取 [建立新的 Azure AD B2C 租使用者]。

    Azure 入口網站 選項來建立新的 Azure AD B2C 租使用者。

  5. 針對 [ 組織名稱 ] 和 [初始功能變數名稱],提供適當的值,然後選取 [ 建立]。

    Azure AD B2C 建立租用戶畫面。

  6. 當 Active Directory 建立完成時,請選取右上角的帳戶,選取 [切換目錄],然後選取已建立的目錄。 系統會將您重新導向至新的租使用者首頁。 然後搜尋 b2c 並選取 [Azure AD B2C]。

    找出 Azure AD B2C 服務。

新增 Spring Boot 應用程式的應用程式註冊

  1. 在 [管理] 窗格中,選取 [應用程式註冊],然後選取 [新增註冊]。

    顯示 Azure AD B2C 應用程式註冊 畫面之 Azure 入口網站 的螢幕快照。

  2. 在 [ 名稱] 欄位中,輸入您的應用程式名稱,然後選取 [ 註冊]。

    Azure AD B2C 註冊應用程式表單。

  3. 回到 [管理] 窗格,選取 [應用程式註冊],然後選取您建立的應用程式名稱。

    已選取顯示名稱的 應用程式註冊 畫面。

  4. 選取 [驗證],然後選取 [新增平臺],然後選取 [Web]。 將 [ 重新導向 URI] 設定為 http://localhost:8080/login/oauth2/code/,然後選取 [ 設定]。

    選取用於驗證的選項、新增平臺、Web。

    已選取 [重新導向 URI] 字段來設定 Web 畫面。

為您的應用程式新增應用程式秘密

選取 [憑證和秘密],然後選取 [新增客戶端密碼]。 輸入您的秘密描述,然後選取 [ 新增]。 建立秘密之後,請選取秘密值旁的複製圖示,複製值以供本文稍後使用。

新增客戶端密碼畫面。

已選取 [複製] 按鈕的 [憑證和秘密] 畫面。

注意

如果您離開 [憑證和秘密] 區 段並返回,您將看不到秘密值。 在此情況下,您必須建立另一個秘密,並複製它以供日後使用。 有時候,產生的秘密值可能包含application.yml檔案中包含有問題的字元,例如反斜杠或反引號。 在此情況下,請捨棄該秘密併產生另一個秘密。

新增使用者流程

  1. 流覽至您的租用戶主頁面。 在左窗格的 [ 原則] 區段中,選取 [使用者流程],然後選取 [ 新增使用者流程]。

  2. 您現在將離開本教學課程、執行另一個教學課程,並在完成時返回本教學課程。 當您前往其他教學課程時,以下是一些要記住的事項。

    • 從要求您選取 [新增使用者流程] 的步驟開始。
    • 當本教學課程 webapp1參考 時,請改用您為 群組 輸入的值。
    • 當您選取要從流程傳回的宣告時,請確定 已選取 [顯示名稱 ]。 如果沒有此宣告,本教學課程中正在建置的應用程式將無法運作。
    • 當系統要求您執行使用者流程時,您先前指定的重新導向 URL 尚未作用中。 您仍然可以執行流程,但重新導向無法順利完成。 這是預期行為。
    • 當您觸達「後續步驟」時,請返回本教學課程。

    遵循教學課程:在 Azure Active Directory B2C 中建立使用者流程,以建立「註冊和登入」、「配置檔編輯」和「密碼重設」的使用者流程。

    Azure AD B2C 支援本機帳戶和社交識別提供者。 如需建立 GitHub 識別提供者的範例,請參閱 使用 Azure Active Directory B2C 以 GitHub 帳戶設定註冊和登入。

設定和編譯您的應用程式

既然您已建立 Azure AD B2C 實例和一些使用者流程,您將將 Spring 應用程式連線到 Azure AD B2C 實例。

  1. 從命令行將 cd 解壓縮您從 Spring Initializr 下載.zip檔案的目錄。

  2. 流覽至專案的父資料夾,然後在文本編輯器中開啟 pom.xml Maven 項目檔。

  3. 將 Spring OAuth2 安全性的 相依性新增至pom.xml

    <dependency>
        <groupId>com.azure.spring</groupId>
        <artifactId>spring-cloud-azure-starter-active-directory-b2c</artifactId>
        <version>See Below</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
        <version>See Below</version>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        <version>See Below</version>
    </dependency>
    

    spring-cloud-azure-starter-active-directory-b2c針對 ,請使用可用的最新版本。 您可以使用 mvnrepository.com 來查閱。

    spring-boot-starter-thymeleaf針對 ,請使用對應至您上面選取之 Spring Boot 版本的版本,例如 2.3.4.RELEASE

    針對 thymeleaf-extras-springsecurity5,請使用可用的最新版本。 您可以使用 mvnrepository.com 來查閱。 從本文起,最新版本是 3.0.4.RELEASE

  4. 儲存並關閉 pom.xml 檔案。

    • 執行 mvn -DskipTests clean install來確認您的相依性是否正確。 如果您沒有看到 BUILD SUCCESS,請先進行疑難解答並解決問題,然後再繼續。
  5. 流覽至 專案中的 src/main/resources 資料夾,並在文字編輯器中建立 application.yml 檔案。

  6. 使用您稍早建立的值來指定應用程式註冊的設定;例如:

    spring:
      cloud:
        azure:
          active-directory:
            b2c:
              enabled: true
              base-uri: https://<your-tenant-initial-domain-name>.b2clogin.com/<your-tenant-initial-domain-name>.onmicrosoft.com/
              credential:
                client-id: <your-application-ID>
                client-secret: '<secret-value>'
              login-flow: sign-up-or-sign-in
              logout-success-url: <your-logout-success-URL>
              user-flows:
                sign-up-or-sign-in: <your-sign-up-or-sign-in-user-flow-name> 
                profile-edit: <your-profile-edit-user-flow-name> 
                password-reset: <your-password-reset-user-flow-name> 
              user-name-attribute-name: <your-user-name-attribute-name> 
    

    請注意,值 client-secret 會以單引弧括住。 這是必要的,因為的值 <secret-value> 幾乎肯定會包含一些字元,需要出現在 YAML 中的單引號內。

    注意

    撰寫本文時,可供application.yml使用的 Active Directory B2C Spring Integration 值完整清單如下:

    spring:
      cloud:
        azure:
          active-directory:
            b2c:
              enabled: true
              base-uri:
              credential:
                client-id:
                client-secret:
              login-flow:  
              logout-success-url:
              user-flows:
                sign-up-or-sign-in:
                profile-edit: # optional
                password-reset: # optional
              user-name-attribute-name:
    

    application.yml檔案可在 GitHub 上的 spring-cloud-azure-starter-active-directory-b2c 範例中取得:aad-b2c-web-application

  7. 儲存並關閉 application.yml 檔案。

  8. src/main/java/<yourGroupId/yourGroupId>> 中<建立名為 controller 的資料夾,並將 取代<yourGroupId>為您為 Group 輸入的值。

  9. 在控制器資料夾中建立名為 WebController.java 的新 Java 檔案,並在文字編輯器中開啟它。

  10. 輸入下列程式代碼,適當地變更 yourGroupId ,然後儲存並關閉檔案:

    package yourGroupId.yourGroupId.controller;
    
    import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
    import org.springframework.security.oauth2.core.user.OAuth2User;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    public class WebController {
    
        private void initializeModel(Model model, OAuth2AuthenticationToken token) {
            if (token != null) {
                final OAuth2User user = token.getPrincipal();
    
                model.addAttribute("grant_type", user.getAuthorities());
                model.addAllAttributes(user.getAttributes());
            }
        }
    
        @GetMapping(value = "/")
        public String index(Model model, OAuth2AuthenticationToken token) {
            initializeModel(model, token);
    
            return "home";
        }
    
        @GetMapping(value = "/greeting")
        public String greeting(Model model, OAuth2AuthenticationToken token) {
            initializeModel(model, token);
    
            return "greeting";
        }
    
        @GetMapping(value = "/home")
        public String home(Model model, OAuth2AuthenticationToken token) {
            initializeModel(model, token);
    
            return "home";
        }
    }
    

    由於控制器中的每個方法都會呼叫 ,而且該方法會呼叫 initializeModel()model.addAllAttributes(user.getAttributes());,因此 src/main/resources/templates 中的任何 HTML 頁面都能夠存取任何這些屬性,例如 ${name}${grant_type}${auth_time}。 從 user.getAttributes() 傳回的值實際上是用於驗證的 id_token 宣告。 可用宣告的完整清單會列在 Microsoft 身分識別平台 識別碼令牌

  11. src/main/java/<yourGroupId/yourGroupId>> 中<建立名為 security 的資料夾,並將 yourGroupId 取代為您為 Group 輸入的值。

  12. 在安全性資料夾中建立名為 WebSecurityConfiguration.java 的新 Java 檔案,並在文字編輯器中開啟它。

  13. 輸入下列程式代碼,適當地變更 yourGroupId ,然後儲存並關閉檔案:

    package yourGroupId.yourGroupId.security;
    
    import com.azure.spring.cloud.autoconfigure.aadb2c.AadB2cOidcLoginConfigurer;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    
    @EnableWebSecurity
    public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        private final AadB2cOidcLoginConfigurer configurer;
    
        public WebSecurityConfiguration(AadB2cOidcLoginConfigurer configurer) {
            this.configurer = configurer;
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                    .anyRequest()
                    .authenticated()
                    .and()
                    .apply(configurer)
            ;
        }
    }
    
  14. 將home.html檔案從 spring-cloud-azure-starter-active-directory-b2c 範例:aad-b2c-web-application 複製到 src/main/resources/templates,並以您稍早建立的使用者流程名稱取代 ${your-profile-edit-user-flow}${your-password-reset-user-flow}

建置和測試您的應用程式

  1. 開啟命令提示字元,並將目錄變更為應用程式 pom.xml 檔案所在的資料夾。

  2. 使用 Maven 建置 Spring Boot 應用程式並加以執行;例如:

    注意

    根據本機 Spring Boot 應用程式執行所在的系統時鐘,時間非常重要。 使用 OAuth 2.0 時,時鐘扭曲的容錯度很小。 即使有三分鐘的不透明度,也可能會導致登入失敗,並出現類似 [invalid_id_token] An error occurred while attempting to decode the Jwt: Jwt used before 2020-05-19T18:52:10Z的錯誤。 從本文開始, time.gov 有一個指標,指出您的時鐘距離實際時間有多遠。 應用程式已成功執行,誤差為 +0.019 秒。

    mvn -DskipTests clean package
    mvn -DskipTests spring-boot:run
    
  3. 在 Maven 建置並啟動您的應用程式之後,請在網頁瀏覽器中開啟 http://localhost:8080/ ;您應該重新導向至登入頁面。

    Web 應用程式登入頁面。

  4. 選取與登入相關的文字連結。 您應該將 Azure AD B2C 重新導向以啟動驗證程式。

  5. 成功登入之後,您應該會看到來自瀏覽器的範例 home page

    Web 應用程式成功登入。

疑難排解

下列各節說明如何解決您可能會遇到的一些問題。

屬性中遺漏屬性名稱

執行範例時,您可能會收到訊息的例外狀況 Missing attribute 'name' in attributes。 此例外狀況的記錄看起來會類似下列輸出:

java.lang.IllegalArgumentException: Missing attribute 'name' in attributes
at org.springframework.security.oauth2.core.user.DefaultOAuth2User.<init>(DefaultOAuth2User.java:67) ~[spring-security-oauth2-core-5.3.6.RELEASE.jar:5.3.6.RELEASE]
at org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser.<init>(DefaultOidcUser.java:89) ~[spring-security-oauth2-core-5.3.6.RELEASE.jar:5.3.6.RELEASE]
at org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService.loadUser(OidcUserService.java:144) ~[spring-security-oauth2-client-5.3.6.RELEASE.jar:5.3.6.RELEASE]
at org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService.loadUser(OidcUserService.java:63) ~[spring-security-oauth2-client-5.3.6.RELEASE.jar:5.3.6.RELEASE]

如果您收到此錯誤,請仔細檢查您在教學課程:在 Azure Active Directory B2C 中建立使用者流程中建立的使用者工作流程。 建立使用者工作流程時,針對 [用戶屬性] 和 [宣告],請務必選擇 [顯示名稱] 的屬性和宣告。 此外,請務必在 application.yml 檔案中正確設定user-name-attribute-name

使用迴圈登入 B2C 端點

此問題很可能是因為的 localhostCookie 受到污染。 清除 Cookie, localhost 然後再試一次。

摘要

在本教學課程中,您已使用 Azure Active Directory B2C 入門版建立新的 Java Web 應用程式、設定新的 Azure AD B2C 租使用者,並在其中註冊新的應用程式,然後將您的應用程式設定為使用 Spring 註釋和類別來保護 Web 應用程式。

清除資源

若不再需要,請使用 Azure 入口網站 來刪除本文中建立的資源,以避免產生非預期的費用。

下一步

若要深入了解 Spring 和 Azure,請繼續閱讀「Azure 上的 Spring」文件中心中的資訊。