知識庫 / Spring / Spring Security RSS 訂閱

Spring Security 與 Auth0 集成

Spring Security
HongKong
5
12:56 PM · Dec 06 ,2025

1. 概述

Auth0 提供用於各種類型的應用程序(如原生應用、單頁面應用和 Web 應用)的 身份驗證和授權服務。 此外,它還允許您實施各種功能,例如單點登錄、社交登錄和多因素身份驗證。

在本教程中,我們將通過分步指南探索 Spring Security 與 Auth0 的集成,並涵蓋 Auth0 賬户的關鍵配置。

2. 設置 Auth0

Auth0 是一個流行的身份驗證即服務 (IDaaS) 平台,可以輕鬆地將身份驗證功能集成到您的應用程序中。 本指南將指導您完成 Auth0 的設置過程。

安裝 Auth0

  1. 創建 Auth0 帳户: 首先,您需要創建一個 Auth0 帳户。 您可以在 https://auth0.com/ 註冊。

  2. 創建應用: 在您的 Auth0 儀表板中,創建一個新的應用程序。 這將允許您管理您的應用程序的身份驗證設置。

  3. 配置應用程序設置: 配置應用程序設置,例如應用程序名稱、域名和應用程序類型。

  4. 安裝 Auth0 JavaScript 客户端庫: 根據您的應用程序類型,安裝 Auth0 JavaScript 客户端庫。 例如,對於 Web 應用程序,您可以使用 npm 安裝:

    npm install auth0-spa-js
    

    或者,對於 React 應用程序,可以使用以下命令:

    npx create-auth0-react
    

    這將會創建一個包含 Auth0 集成配置的 React 項目。

  5. 配置 Auth0 應用程序設置: 在 Auth0 儀表板中,配置您的應用程序的身份驗證設置,例如客户端 ID 和客户端密鑰。 這些值將用於在您的應用程序中配置 Auth0 集成。

  6. 集成 Auth0 到您的應用程序: 使用 Auth0 提供的 SDK 或 API,將 Auth0 集成到您的應用程序中。 這通常涉及在您的應用程序中添加 Auth0 JavaScript 客户端庫,並使用 SDK 或 API 來處理身份驗證流程。

    // 示例:使用 Auth0-spa-js 登錄
    const auth0 = require('auth0-spa-js');
    
    auth0.extend({
      // ... 您的 Auth0 配置
    });
    
    auth0.authorize({
      redirect_uri: 'YOUR_REDIRECT_URI',
      response_type: 'token',
      scope: 'openid profile email'
    });
    

2.1. 使用 Auth0 註冊

首先,我們將 註冊一個免費的 Auth0 計劃,該計劃可為最多 7000 名活躍用户提供無限登錄權限。 但是,如果已經擁有一個,則可以跳過此部分:

2.2. 儀表盤

登錄到 Auth0 賬户後,您將看到一個儀表盤,它會突出顯示諸如登錄活動、最新登錄和新註冊用户的詳細信息:

2.3. 創建新應用程序

然後,從“應用程序”菜單中,我們將創建一個用於 Spring Boot 的新 OpenID Connect (OIDC) 應用程序。

此外,我們將選擇常規 Web 應用程序作為應用程序類型,從可用的選項中選擇,例如本機應用程序單頁應用程序機器對機器應用程序

2.4. 應用程序設置

接下來,我們將配置一些應用程序 URI,例如 回調 URL註銷 URL,指向我們的應用程序:

2.5. 客户端憑據

最後,我們將獲取與我們的應用程序關聯的 域名客户端 ID客户端密鑰 的值:

請妥善保管這些憑據,因為它們在我們的 Spring Boot 應用程序的 Auth0 設置中是必需的。

3. Spring Boot 應用設置

現在,我們的 Auth0 賬户已準備就緒,並配置了關鍵設置,我們已準備好將 Auth0 安全集成到 Spring Boot 應用中。

3.1. Maven

首先,我們將最新的 mvc-auth-commons Maven 依賴添加到我們的 pom.xml 中:

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>mvc-auth-commons</artifactId>
    <version>1.2.0</version>
</dependency>

3.2. Gradle

同樣地,在使用 Gradle 時,可以在 build.gradle文件中添加 mvc-auth-commons依賴:

compile 'com.auth0:mvc-auth-commons:1.2.0'

3.3. application.properties</h3

我們的 Spring Boot 應用需要 客户端 ID客户端密鑰 以啓用 Auth0 賬户的身份驗證。因此,我們將它們添加到 application.properties 文件中:

com.auth0.domain: dev-example.auth0.com
com.auth0.clientId: {clientId}
com.auth0.clientSecret: {clientSecret}

3.4. AuthConfig

接下來,我們將創建 AuthConfig 類,用於從 application.properties 文件中讀取 Auth0 屬性:

@Configuration
@EnableWebSecurity
public class AuthConfig {
    @Value(value = "${com.auth0.domain}")
    private String domain;

    @Value(value = "${com.auth0.clientId}")
    private String clientId;

    @Value(value = "${com.auth0.clientSecret}")
    private String clientSecret;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf()
          .disable()
          .authorizeRequests()
          .antMatchers("/callback", "/login", "/").permitAll()
          .anyRequest().authenticated()
          .and()
          .formLogin()
          .loginPage("/login")
          .and()
          .logout().logoutSuccessHandler(logoutSuccessHandler()).permitAll();
        return http.build();
    }
}

此外,AuthConfig 類配置為通過創建 SecurityFilterChain 豆啓用 Web 安全性。

3.5. AuthenticationController

最後,我們將 AuthenticationController 類作為 Bean 引用添加到我們之前討論的 AuthConfig 類中:

@Bean
public AuthenticationController authenticationController() throws UnsupportedEncodingException {
    JwkProvider jwkProvider = new JwkProviderBuilder(domain).build();
    return AuthenticationController.newBuilder(domain, clientId, clientSecret)
      .withJwkProvider(jwkProvider)
      .build();
}

在這裏,我們使用了 JwkProviderBuilder 類來構建 AuthenticationController 類的實例。我們將使用它來獲取公鑰以驗證令牌的簽名(默認情況下,令牌使用 RS256 非對稱簽名算法進行簽名)。

此外,authenticationController Bean 提供了一個用於登錄的授權 URL,並處理回調請求。

4. AuthController

接下來,我們將創建用於登錄和回調功能的 AuthController 類:

@Controller
public class AuthController {
    @Autowired
    private AuthConfig config;

    @Autowired 
    private AuthenticationController authenticationController;
}

在這裏,我們已注入了上一節中 AuthConfig 類和 AuthenticationController 控制器的依賴項。

4.1. 登錄

讓我們創建一個 login 方法,允許我們的 Spring Boot 應用驗證用户:

@GetMapping(value = "/login")
protected void login(HttpServletRequest request, HttpServletResponse response) {
    String redirectUri = "http://localhost:8080/callback";
    String authorizeUrl = authenticationController.buildAuthorizeUrl(request, response, redirectUri)
      .withScope("openid email")
      .build();
    response.sendRedirect(authorizeUrl);
}

buildAuthorizeUrl 方法生成 Auth0 授權 URL 並重定向到默認的 Auth0 登錄屏幕。

4.2. 回調 (Callback)

一旦用户使用 Auth0 憑據登錄,回調請求將被髮送到我們的 Spring Boot 應用。為此,讓我們創建一個 callback 方法:

@GetMapping(value="/callback")
public void callback(HttpServletRequest request, HttpServletResponse response) {
    Tokens tokens = authenticationController.handle(request, response);
    
    DecodedJWT jwt = JWT.decode(tokens.getIdToken());
    TestingAuthenticationToken authToken2 = new TestingAuthenticationToken(jwt.getSubject(),
      jwt.getToken());
    authToken2.setAuthenticated(true);
    
    SecurityContextHolder.getContext().setAuthentication(authToken2);
    response.sendRedirect(config.getContextPath(request) + "/"); 
}

我們處理了回調請求以獲取 accessTokenidToken,它們代表了成功的身份驗證。然後,我們創建了 TestingAuthenticationToken 對象,用於在 SecurityContextHolder 中設置身份驗證。

但是,我們可以創建 AbstractAuthenticationToken 類來實現更友好的自定義實現。

5. HomeController

最後,我們將創建一個 HomeController,併為其設置默認映射,用於應用程序的默認主頁:

@Controller
public class HomeController {
    @GetMapping(value = "/")
    @ResponseBody
    public String home(final Authentication authentication) {
        TestingAuthenticationToken token = (TestingAuthenticationToken) authentication;
        DecodedJWT jwt = JWT.decode(token.getCredentials().toString());
        String email = jwt.getClaims().get("email").asString();
        return "Welcome, " + email + "!";
    }
}

在這裏,我們從 DecodedJWT 對象中提取了 idToken。 此外,我們還從聲明(claims)中獲取用户信息,例如電子郵件。

這就完成了! 我們的 Spring Boot 應用已準備好並帶有 Auth0 安全支持。 讓我們使用 Maven 命令運行我們的應用:

mvn spring-boot:run

訪問應用程序至 localhost:8080/login,我們將看到 Auth0 提供的一頁默認登錄頁面:

使用註冊用户憑據登錄後,將顯示包含用户電子郵件地址的歡迎消息:

此外,我們會在默認登錄屏幕上找到“註冊”按鈕(位於“登錄”按鈕旁邊),用於自助註冊。

6. 註冊

6.1. 自注冊

首次使用時,可以通過“註冊”按鈕創建 Auth0 賬户,並提供如電子郵件和密碼等信息:

6.2. 創建用户

或者,我們可以從 Auth0 賬户的 Users 菜單中創建一個新用户:

6.3. 連接設置

此外,我們還可以選擇多種連接類型,例如數據庫和社交登錄,用於我們的 Spring Boot 應用的註冊/登錄:

此外,還提供多種社交連接供您選擇:

7. LogoutController

現在我們已經瞭解了登錄和回調功能,現在可以為我們的 Spring Boot 應用添加註銷功能。

讓我們創建 LogoutController 類,該類實現了 LogoutSuccessHandler 接口:

@Controller
public class LogoutController implements LogoutSuccessHandler {
    @Autowired
    private AuthConfig config;

    @Override
    public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse res, 
      Authentication authentication) {
        if (req.getSession() != null) {
            req.getSession().invalidate();
        }
        String returnTo = "http://localhost:8080/";
        String logoutUrl = "https://dev-example.auth0.com/v2/logout?client_id=" +
          config.getClientId() + "&returnTo=" +returnTo;
        res.sendRedirect(logoutUrl);
    }
}

在這裏,onLogoutSuccess方法被覆蓋以調用 Auth0 的 /v2/logout 身份驗證註銷 URL。

8. Auth0 管理 API

此前,我們已經瞭解了 Spring Boot 應用中的 Auth0 安全集成。現在,讓我們在同一應用中與 Auth0 管理 API(系統 API)進行交互。

8.1. 創建新應用程序

首先,要訪問 Auth0 Management API,我們需要在 Auth0 賬户中創建一個 機器對機器應用程序

8.2. 授權

然後,我們將為 Auth0 Management API 添加授權功能,包括讀取/創建用户權限:

8.3. 客户端憑據

最後,我們將收到 客户端 ID客户端密鑰,以便從我們的 Spring Boot 應用訪問 Auth0 管理應用:

8.4. 訪問令牌

以下我們使用前一節中接收到的客户端憑據,為 Auth0 管理應用程序生成訪問令牌:

public String getManagementApiToken() {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);

    JSONObject requestBody = new JSONObject();
    requestBody.put("client_id", "auth0ManagementAppClientId");
    requestBody.put("client_secret", "auth0ManagementAppClientSecret");
    requestBody.put("audience", "https://dev-example.auth0.com/api/v2/");
    requestBody.put("grant_type", "client_credentials"); 

    HttpEntity<String> request = new HttpEntity<String>(requestBody.toString(), headers);

    RestTemplate restTemplate = new RestTemplate();
    HashMap<String, String> result = restTemplate
      .postForObject("https://dev-example.auth0.com/oauth/token", request, HashMap.class);

    return result.get("access_token");
}

在這裏,我們向 /oauth/token Auth0 Token URL 發起了 REST 請求,以獲取訪問和刷新令牌。

此外,我們可以在 application.properties 文件中存儲這些客户端憑據,並使用 AuthConfig 類進行讀取。

8.5. UserController

之後,讓我們創建一個 UserController 類,其中包含 users 方法:

@Controller
public class UserController {
    @GetMapping(value="/users")
    @ResponseBody
    public ResponseEntity<String> users(HttpServletRequest request, HttpServletResponse response) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + getManagementApiToken());
        
        HttpEntity<String> entity = new HttpEntity<String>(headers);
        
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> result = restTemplate
          .exchange("https://dev-example.auth0.com/api/v2/users", HttpMethod.GET, entity, String.class);
        return result;
    }
}

users 方法通過向生成的上一節中訪問令牌生成的 /api/v2/users Auth0 API 發送 GET 請求,獲取所有用户列表。

因此,讓我們訪問 localhost:8080/users 以接收包含所有用户的 JSON 響應:

[{
    "created_at": "2020-05-05T14:38:18.955Z",
    "email": "[email protected]",
    "email_verified": true,
    "identities": [
        {
            "user_id": "5eb17a5a1cc1ac0c1487c37f78758",
            "provider": "auth0",
            "connection": "Username-Password-Authentication",
            "isSocial": false
        }
    ],
    "name": "[email protected]",
    "nickname": "ansh",
    "logins_count": 64
    // ...
}]

8.6. 創建用户

類似於創建用户,我們可以通過向 Auth0 API 發送 POST 請求來創建用户:

具體來説,我們向 /api/v2/users Auth0 API 發送 POST 請求。

@GetMapping(value = "/createUser")
@ResponseBody
public ResponseEntity<String> createUser(HttpServletResponse response) {
    JSONObject request = new JSONObject();
    request.put("email", "[email protected]");
    request.put("given_name", "Norman");
    request.put("family_name", "Lewis");
    request.put("connection", "Username-Password-Authentication");
    request.put("password", "Pa33w0rd");
    
    // ...
    ResponseEntity<String> result = restTemplate
      .postForEntity("https://dev-example.auth0.com/api/v2/users", request.toString(), String.class);
    return result;
}

然後,讓我們訪問 localhost:8080/createUser 並驗證新用户的詳細信息:

{
    "created_at": "2020-05-10T12:30:15.343Z",
    "email": "[email protected]",
    "email_verified": false,
    "family_name": "Lewis",
    "given_name": "Norman",
    "identities": [
        {
            "connection": "Username-Password-Authentication",
            "user_id": "5eb7f3d76b69bc0c120a8901576",
            "provider": "auth0",
            "isSocial": false
        }
    ],
    "name": "[email protected]",
    "nickname": "norman.lewis",
    // ...
}

同樣,我們還可以使用 Auth0 API 執行各種操作,例如列出所有連接、創建連接、列出所有客户端以及創建客户端,具體操作取決於我們的權限。

9. 結論

在本教程中,我們探討了 Spring Security 與 Auth0 的集成。

首先,我們設置了 Auth0 賬户,並完成了必要的配置。然後,我們創建了一個 Spring Boot 應用,並配置了 application.properties 以進行 Spring Security 與 Auth0 的集成。

接下來,我們研究了創建 Auth0 管理 API 令牌的方法。最後,我們研究了諸如獲取所有用户和創建用户等功能。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.