返回

如何在 Spring Boot 中使用 Keycloak 保护 REST API?

java

在构建现代化的分布式系统时,API 的安全防护可谓重中之重。如何确保只有授权用户才能访问敏感数据和功能?Spring Boot 和 Keycloak 这对组合提供了一个强大的解决方案。本文将带你一步步构建一个安全的 REST API,涵盖配置、测试和故障排除等关键环节,为你打造坚不可摧的应用保驾护航。

首先,我们需要为 Spring Boot 应用添加必要的依赖。打开项目的 pom.xml 文件,添加 spring-boot-starter-oauth2-resource-server 依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>

这段代码的作用是引入 Spring Security OAuth2 资源服务器的功能,让你的应用能够验证 Keycloak 颁发的访问令牌。

接下来,我们需要告诉 Spring Boot 应用去哪里验证令牌。在 application.propertiesapplication.yml 文件中,设置 Keycloak 服务器的 issuer-uri

spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8083/realms/realm_1/.well-known/openid-configuration

这个 issuer-uri 指向 Keycloak 服务器的 OpenID Connect 配置端点,Spring Boot 应用将使用它来获取验证令牌所需的公钥和其他信息。

现在,轮到 Keycloak 登场了。首先,确保你的 Keycloak 服务器已经启动并运行。然后,我们需要在 Keycloak 中创建一个新的领域和客户端。

  1. 创建领域: 登录 Keycloak 管理控制台,创建一个名为 "realm_1" 的领域。你可以把它想象成一个独立的安全管理区域。
  2. 创建客户端: 在 "realm_1" 领域中,创建一个名为 "client-1" 的客户端。客户端代表你的 Spring Boot 应用,它需要通过 Keycloak 进行身份验证和授权。将客户端类型设置为 "confidential",这意味着客户端拥有自己的密钥,可以安全地存储凭据。
  3. 设置重定向 URI: 在客户端设置中,将 "Valid Redirect URIs" 设置为 http://localhost:8080/login/oauth2/code/keycloak。这是 Spring Boot 应用在用户成功登录 Keycloak 后将被重定向到的地址。同时,将 "Web Origins" 设置为 +,允许所有来源的请求。
  4. 映射客户端权限和用户: 在客户端的 "Service Account Roles" 中,将 "client-1" 客户端的 "Service Account User" 角色映射到 "offline_access" 和 "uma_authorization" 权限。这将允许客户端代表用户访问资源,即使用户离线。此外,创建一个名为 "user1" 的用户,并将其添加到 "client-1" 客户端。

完成 Keycloak 的配置后,我们就可以开始编写 REST 控制器了。创建一个新的控制器类,并使用 @RestController 注解标记它:

@RestController
public class AppRestController {

    @GetMapping("/authenticated")
    @PreAuthorize("isAuthenticated()")
    public String authenticated() {
        return "authenticated";
    }

    @GetMapping("/permitAll")
    @PreAuthorize("permitAll")
    public String permitAll() {
        return "permitAll";
    }

    @GetMapping("/support")
    @PreAuthorize("hasRole('support')")
    public String support() {
        return "support";
    }
}

我们使用 @PreAuthorize 注解来保护不同的端点:

  • /authenticated 端点需要用户进行身份验证才能访问。
  • /permitAll 端点允许任何用户访问,无需身份验证。
  • /support 端点只有拥有 "support" 角色的用户才能访问。

现在,激动人心的时刻到了,让我们来测试一下我们构建的安全 API。

  1. 启动 Spring Boot 应用: 运行你的 Spring Boot 应用。
  2. 获取访问令牌: 你可以使用 Keycloak 的管理控制台或 Postman 等工具来获取访问令牌。你需要提供客户端 ID、客户端密钥和用户的凭据才能获取令牌。
  3. 调用受保护端点: 使用获取到的访问令牌,调用 /authenticated/support 端点。你应该能够成功访问 /authenticated 端点,但访问 /support 端点会返回 403 Forbidden 错误,除非你使用拥有 "support" 角色的用户登录。

在实际应用中,还有一些额外的安全措施可以考虑:

  • 启用 HTTPS: 为你的 Spring Boot 应用和 Keycloak 服务器启用 HTTPS,确保通信安全。
  • 使用 OpenID Connect Discovery: 你可以使用 OpenID Connect Discovery 来自动配置 issuer-uri,而无需手动指定。
  • 定期轮换令牌: 定期轮换访问令牌,降低令牌被盗或滥用的风险。

常见问题解答

  1. 为什么选择 Keycloak 而不是其他 OAuth 2.0 身份验证服务器?
    Keycloak 是一款开源的身份验证和授权服务器,功能丰富且易于使用,它提供了单点登录、用户联合、身份代理等功能,可以满足各种应用场景的需求。

  2. 如何防止令牌被盗或滥用?
    除了定期轮换令牌,还可以使用 JWT 的 exp (expiration time) 字段设置令牌的过期时间,并使用 jti (JWT ID) 字段防止重放攻击。

  3. 如何调试受保护端点的问题?
    可以查看 Spring Boot 和 Keycloak 的日志文件,检查配置是否正确,并验证传入的令牌是否有效。

  4. Keycloak 可以保护非 Web API 吗?
    当然可以!Keycloak 可以保护各种类型的 API,包括 RESTful 微服务、GraphQL API 等。

  5. 如何扩展此安全配置?
    你可以集成其他安全措施,例如多因素身份验证、API 网关等,进一步增强 API 的安全性。

通过本文的介绍,相信你已经掌握了使用 Spring Boot 和 Keycloak 构建安全 REST API 的基本方法。记住,安全是一个持续的过程,需要不断学习和改进。祝你构建出安全可靠的应用程序!