Spring Cloud Gateway OAuth2后端服务构建:SpringOpaqueTokenIntrospector类型错误
问题:SpringOpaqueTokenIntrospector 类型不匹配编译错误
背景
我参考《Using Spring Cloud Gateway with OAuth 2.0 Patterns》教程构建后端服务,已完成以下配置:
Maven依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>ru.test.gw.oauth.resource</groupId> <artifactId>backresource</artifactId> <version>0.0.1-SNAPSHOT</version> <name>backresource</name> <description>Demo project for Spring Boot</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>14</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <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-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
配置文件
server.port=11002 # Resource server settings spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=http://localhost:8484/auth/realms/demo/protocol/openid-connect/token/introspect spring.security.oauth2.resourceserver.opaquetoken.client-id=gateway spring.security.oauth2.resourceserver.opaquetoken.client-secret=dfdslksfkljweewrfsd
自定义KeycloakReactiveTokenInstrospector类
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal; import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector; import reactor.core.publisher.Mono; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; // Custom ReactiveTokenIntrospector to map realm roles into Spring GrantedAuthorities public class KeycloakReactiveTokenInstrospector implements ReactiveOpaqueTokenIntrospector { private final ReactiveOpaqueTokenIntrospector delegate; public KeycloakReactiveTokenInstrospector(ReactiveOpaqueTokenIntrospector delegate) { this.delegate = delegate; } @Override public Mono<OAuth2AuthenticatedPrincipal> introspect(String token) { return delegate.introspect(token) .map( this::mapPrincipal); } protected OAuth2AuthenticatedPrincipal mapPrincipal(OAuth2AuthenticatedPrincipal principal) { return new DefaultOAuth2AuthenticatedPrincipal( principal.getName(), principal.getAttributes(), extractAuthorities(principal)); } protected Collection<GrantedAuthority> extractAuthorities(OAuth2AuthenticatedPrincipal principal) { Map<String,List<String>> realm_access = principal.getAttribute("realm_access"); List<String> roles = realm_access.getOrDefault("roles", Collections.emptyList()); List<GrantedAuthority> rolesAuthorities = roles.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); Set<GrantedAuthority> allAuthorities = new HashSet<>(); allAuthorities.addAll(principal.getAuthorities()); allAuthorities.addAll(rolesAuthorities); return allAuthorities; } }
项目主类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.PropertySource; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.oauth2.server.resource.introspection.NimbusReactiveOpaqueTokenIntrospector; import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector; import ru.test.gw.oauth.resource.backresource.security.KeycloakReactiveTokenInstrospector; @SpringBootApplication //@PropertySource("classpath:quotes-application.properties") @EnableWebFluxSecurity public class BackresourceApplication { public static void main(String[] args) { SpringApplication.run(BackresourceApplication.class, args); } @Bean public SpringOpaqueTokenIntrospector keycloakIntrospector(OAuth2ResourceServerProperties props) { NimbusReactiveOpaqueTokenIntrospector delegate = new NimbusReactiveOpaqueTokenIntrospector( props.getOpaquetoken().getIntrospectionUri(), props.getOpaquetoken().getClientId(), props.getOpaquetoken().getClientSecret()); return new KeycloakReactiveTokenInstrospector(delegate); } }
问题描述
主类中的SpringOpaqueTokenIntrospector提示未定义,按IDE提示导入org.springframework.security.oauth2.server.resource.introspection.SpringOpaqueTokenIntrospector后,出现类型不匹配错误:Type mismatch: cannot convert from KeycloakReactiveTokenInstrospector to SpringOpaqueTokenIntrospector,需要解决编译错误完成项目构建。
解决方案
1. 修正Bean返回类型
问题核心是类型匹配错误:
- 自定义类
KeycloakReactiveTokenInstrospector实现的是反应式Token内省接口ReactiveOpaqueTokenIntrospector SpringOpaqueTokenIntrospector是同步场景的接口,和当前WebFlux反应式架构不兼容
修改主类中的Bean定义,将返回类型改为ReactiveOpaqueTokenIntrospector:
@Bean public ReactiveOpaqueTokenIntrospector keycloakIntrospector(OAuth2ResourceServerProperties props) { NimbusReactiveOpaqueTokenIntrospector delegate = new NimbusReactiveOpaqueTokenIntrospector( props.getOpaquetoken().getIntrospectionUri(), props.getOpaquetoken().getClientId(), props.getOpaquetoken().getClientSecret()); return new KeycloakReactiveTokenInstrospector(delegate); }
2. 补充自定义类的缺失导入
你的自定义类中缺少集合和流操作的必要导入,需补充到类顶部:
import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors;
3. 依赖确认
当前使用的spring-boot-starter-oauth2-resource-server(Spring Boot 2.7.5版本)已经包含反应式Token内省所需的所有类,无需额外添加依赖。
内容的提问来源于stack exchange,提问作者alexmntmnk
相关产品推荐
相关产品推荐

