使用Spring Cloud GatewayFilter的伪造客户端导致周期依赖



在某些检查期间,我需要在网关过滤器中向我的微服务发出请求。当我在GatewayFilter(我的SecurityFilter.java)类中定义Feign类时,它给出了以下错误。我该如何解决这个问题呢?

错误:

Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
|  securityFilter defined in file [/target/classes/com/example/SecurityFilter.class]
↑     ↓
|  cachedCompositeRouteLocator defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]
↑     ↓
|  routeDefinitionRouteLocator defined in class path resource [org/springframework/cloud/gateway/config/GatewayAutoConfiguration.class]
└─────┘

Action:
Despite circular references being allowed, the dependency cycle between beans could not be broken. Update your application to remove the dependency cycle.
<<p>GatewayFilter类/strong>
@Component
public class SecurityFilter implements GatewayFilterFactory<SecurityFilter.Config> {
private final UserApi userApi;
public SecurityFilter(UserApi userApi) {
this.userApi = userApi;
}
@Override
public GatewayFilter apply(Config config) {
return ((exchange, chain) -> {
return chain.filter(exchange.mutate().request(exchange.getRequest()).build());
});
}
@Override
public Class<Config> getConfigClass() {
return Config.class;
}
@Override
public Config newConfig() {
Config c = new Config();
return c;
}
public static class Config {
}
}

pom.xml

<properties>
<java.version>17</java.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</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-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

主类

@SpringBootApplication
@ComponentScan("com.example")
@EnableFeignClients(basePackages = {"com.example.feign"})
public class GatewayApplicationMain {
public static void main(String[] args) {
SpringApplication.run(GatewayApplicationMain.class, args);
}
}

伪造api类

@FeignClient(name = "user", path="userService/", url="http://localhost:8091/")
public interface UserApi {
@GetMapping("/getUserByUserName/{userName}")
ResponseEntity<Object> getUserByUserName(@PathVariable(name = "userName") String userName);
}

安全类

@Configuration
public class SecurityConfig {
@Bean
public SecurityWebFilterChain configure(ServerHttpSecurity http) {
http.csrf().disable()
.authorizeExchange()
.anyExchange()
.authenticated()
.and()
.oauth2Login()
.and().oauth2ResourceServer().jwt();
return http.build();
}
}

应用程序。属性文件

server.port=8090
spring.main.allow-circular-references=true
private final UserApi userApi;
@Autowired
public SecurityFilter(@Lazy UserApi userApi) {
this.userApi = userApi;
}

这就是我如何通过添加@Lazy来解决问题的。

如果你想保持循环依赖,你可以添加这个配置

spring.main.allow-circular-references: true

我使用@Lazy注释每当伪造客户端意图被使用,以避免循环引用错误时使用spring-cloud-gateway与OpenFeign,即使在我的CustomGatewayFilter:)

@Component
public class CustomApiGatewayFilter extends AbstractGatewayFilterFactory<CustomApiGatewayFilter.Config> {
private static Logger logger = LogManager.getLogger(CustomApiGatewayFilter.class);
private final JwtConfig jwtConfig;
private final ThirdPartyFeignClientService thirdPartyFeignClientService;
public CustomApiGatewayFilter(JwtConfig jwtConfig, @Lazy ThirdPartyFeignClientService thirdPartyFeignClientService) {
super(Config.class);
this.jwtConfig = jwtConfig;
this.thirdPartyFeignClientService = thirdPartyFeignClientService;
}
....
....
}

这个虚拟客户端的使用放在这个过滤器使用的一个单独的函数上

private String validateToken(String jwtToken) throws MyAppException {
String json = "";
ObjectMapper mapper = new ObjectMapper();
try {
Claims claims = jwtConfig.getAllClaimsFromToken(jwtToken);
String additionalInfo = (String) claims.get("additionalInfo");
JwtPayload payload = mapper.readValue(additionalInfo, JwtPayload.class);
String username = jwtConfig.getUsernameFromToken(jwtToken);
if(thirdPartyFeignClientService.validateClient(payload.getClientId(), payload.getClientSecret())){
return username;
}else{
throw new MyAppException("Invalid Client", ErrorCode.GENERIC_FAILURE);
}
} catch (ExpiredJwtException e) {
logger.error(e.getMessage());
throw new MyAppException(e.getMessage(), ErrorCode.GENERIC_FAILURE);
} catch (Exception e) {
logger.error("Other Exception :" + e);
throw new MyAppException (e.getMessage(), ErrorCode.GENERIC_FAILURE);
}
}

它工作了:)

相关内容

  • 没有找到相关文章

最新更新