我正在 Spring Boot 应用程序中使用 Feign 来与 Keycloak 的令牌端点集成。我有以下 Feign 客户端设置来请求访问令牌:
@FeignClient(name = "auth-service", url = "${keycloak.auth-server-url}/realms")
public interface KeyCloakAuthServiceClient {
@PostMapping(value = "/{realm}/protocol/openid-connect/token",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
@Headers("Content-Type: application/x-www-form-urlencoded")
AccessTokenResponse getAccessToken(@PathVariable("realm") String realm,
MultiValueMap<String, String> formParams);
class Configuration {
@Bean
Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> converters) {
return new SpringFormEncoder(new SpringEncoder(converters));
}
}
}
即使我在 MultiValueMap 中传递必要的参数,此设置始终无法与 Keycloak 的令牌端点进行通信。但是,一旦我从@PostMapping注释中删除了consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,一切就开始工作并且我能够接收令牌。
为什么当@PostMapping注解中包含consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE时,Feign无法处理请求,为什么当我删除它时它可以工作,即使内容类型仍然是application/x-www-form-urlencoded? Consumers 属性和 @Headers 注释之间是否存在冲突,或者这可能是另一个问题?
任何关于为什么会发生这种情况或我可能会错过什么的见解将不胜感激!
我最初将
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE
添加到 @PostMapping
注释中,期望它能够正确设置表单编码请求的内容类型。我还添加了 @Headers("Content-Type: application/x-www-form-urlencoded")
注释,以确保在请求中发送正确的内容类型。
我验证了
MultiValueMap
包含所有必需的表单参数,例如client_id
、grant_type
、username
、password
等。但是,请求始终失败,我无法从Keycloak检索令牌。
然后,我删除了
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE
部分,令我惊讶的是,请求完美地工作了,我收到了来自Keycloak的访问令牌。
我希望 Feign 客户端能够使用
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE
注释中的 @PostMapping
和 @Headers("Content-Type: application/x-www-form-urlencoded")
,因为这应该指示 Feign 将表单编码的请求发送到令牌端点。然而,只有在删除了consumes属性后才起作用,这是我没想到的。
根据规范,您的
@FeignClient
应该产生application/x-www-form-urlencoded
(发送带有该格式参数的请求)并消耗application/json
(读取该格式的响应)。显然,你正试图做相反的事情......