You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Keycloak认证模块实现REST API模块的SSO权限管控?

基于Spring Boot的Keycloak SSO保护REST API+Swagger集成方案

针对你提到的两个模块(Keycloak+Swagger集成模块、需SSO保护的REST API模块),以下是稳定可行的配置方案——放弃易出问题的旧Keycloak适配器,采用Spring官方OAuth2组件实现:


1. 先完成Keycloak服务端基础配置

确保Keycloak后台已完成以下配置:

  • 创建专属Realm(比如my-realm)
  • 为API模块创建客户端:访问类型选confidential,开启Service Accounts Enabled,记录客户端ID和密钥
  • 为Swagger模块创建客户端:访问类型选public,重定向URI设为http://localhost:8081/swagger-ui/**(对应Swagger模块端口),记录客户端ID
  • 为测试用户分配对应角色(比如api-access),确保角色在Realm的realm_access.roles字段中

2. 受保护的REST API模块配置

2.1 依赖配置(pom.xml)

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

2.2 配置文件(application.yml)

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://localhost:8080/realms/my-realm
          jwk-set-uri: ${spring.security.oauth2.resourceserver.jwt.issuer-uri}/protocol/openid-connect/certs

server:
  port: 8082 # API模块独立端口

2.3 Spring Security核心配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class ApiSecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated() // 所有API接口强制认证
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()))
            );
        return http.build();
    }

    // 可选:将Keycloak角色映射为Spring Security权限
    private JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter();
        converter.setAuthorityPrefix("ROLE_");
        converter.setAuthoritiesClaimName("realm_access.roles");

        JwtAuthenticationConverter authConverter = new JwtAuthenticationConverter();
        authConverter.setJwtGrantedAuthoritiesConverter(converter);
        return authConverter;
    }
}

配置完成后,所有API接口会强制要求请求头携带Authorization: Bearer <JWT_TOKEN>,未携带或无效Token会返回401。


3. Keycloak+Swagger集成模块配置

3.1 依赖配置(pom.xml)

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        <version>2.2.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>

3.2 配置文件(application.yml)

spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: swagger-client # 对应Keycloak中创建的Swagger客户端ID
            scope: openid, profile, api-access
            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/keycloak"
        provider:
          keycloak:
            issuer-uri: http://localhost:8080/realms/my-realm
            user-name-attribute: preferred_username

server:
  port: 8081 # Swagger模块独立端口

springdoc:
  swagger-ui:
    oauth:
      client-id: swagger-client
      realm: my-realm
      app-name: API测试客户端
      use-pkce-with-authorization-code-grant: true

3.3 Spring Security配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SwaggerSecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
                .anyRequest().authenticated()
            )
            .oauth2Login(oauth2 -> oauth2
                .defaultSuccessUrl("/swagger-ui/index.html", true) // 登录成功后跳转到Swagger UI
            );
        return http.build();
    }
}

3.4 Swagger OpenAPI配置

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class OpenApiConfig {

    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
            .addSecurityItem(new SecurityRequirement().addList("BearerAuth"))
            .components(new Components()
                .addSecuritySchemes("BearerAuth", new SecurityScheme()
                    .type(SecurityScheme.Type.HTTP)
                    .scheme("bearer")
                    .bearerFormat("JWT")
                    .in(SecurityScheme.In.HEADER)
                    .name("Authorization")
                )
            );
    }
}

配置完成后,访问Swagger UI会自动跳转到Keycloak登录页,登录成功后可通过Swagger的「Authorize」按钮携带Token调用受保护的API接口。


常见启动问题排查

  1. 若之前用旧Keycloak适配器启动失败,直接切换到上述Spring OAuth2方案即可——Keycloak官方已弃用旧适配器,Spring 3+完全兼容OAuth2组件
  2. 检查issuer-uri是否可访问:确保Keycloak服务正常,能打开http://localhost:8080/realms/my-realm/.well-known/openid-configuration
  3. 客户端配置校验:API模块客户端必须是confidential类型,Swagger模块若为public类型则不能配置client-secret
  4. 端口冲突:两个模块必须使用不同端口

内容的提问来源于stack exchange,提问作者FAIZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:58:31