Request Interceptor Feign 客户端的 403 响应
403 response with Request Interceptors Feing client
我有一个假装客户端的请求拦截器配置,我想验证它是否配置正确。假设向 auth url 发出请求并获得授权。
这似乎工作正常。但我认为它并没有把它放在发送到资源服务器的每个请求中。因此我一直收到 403。但是当我使用我的代码中生成的身份验证令牌在邮递员上尝试此操作时,它工作正常。
下面是代码
@Component
public class FeignC2aSystemOAuthInterceptor implements RequestInterceptor {
@Value("${c2a.oauth2.clientId}")
private String clientId;
@Value("${c2a_system.authUrl}")
private String authUrl;
@Value("${c2a.oauth2.clientSecret}")
private String clientSecret;
private String jwt;
private LocalDateTime expirationDate = LocalDateTime.now();
private final RestTemplate restTemplate;
public FeignC2aSystemOAuthInterceptor(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public void apply(RequestTemplate requestTemplate) {
if (LocalDateTime.now().isAfter(expirationDate)) {
requestToken();
System.out.println("JUST AFTER REQUEST" + this.jwt);
}
/* use the token */
System.out.println("USE THE TOKEN" + this.jwt);
requestTemplate.header("Authorization: Bearer " + this.jwt);
}
private void requestToken() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("client_id", clientId);
map.add("client_secret", clientSecret);
map.add("grant_type", "client_credentials");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<C2AAuthResponse> response = restTemplate.postForEntity(authUrl, request, C2AAuthResponse.class);
this.jwt = Objects.requireNonNull(response.getBody()).getAccessToken();
LocalDateTime localDateTime = LocalDateTime.now();
this.expirationDate = localDateTime.plusSeconds(response.getBody().getExpiresIn());
}
配置
@Configuration
public class FeignC2aSystemConfig {
@Bean
RestTemplate getRestTemplate() {
return new RestTemplate();
};
@Bean
FeignC2aSystemOAuthInterceptor fen () {
return new FeignC2aSystemOAuthInterceptor(getRestTemplate());
}
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
和客户
@FeignClient(name = "c2aSystem", url = "${c2a_system.base_url}", configuration = FeignC2aSystemConfig.class)
public interface C2AApiClient {
@PostMapping(value = C2ASystemIntegrationUrls.SEND, produces = "application/json", consumes = "application/json")
HttpServletResponse sendSms(@RequestBody C2aMessage c2aMessage);
@GetMapping(value = C2ASystemIntegrationUrls.GETLIST, produces = "application/json", consumes = "application/json")
List<MessageData> getMessages();
}
在记录期间,我注意到它调用了拦截器,并且我可以看到使用 sout 记录的身份验证令牌。
我想知道我是否在某个地方弄得一团糟,可能导致它无法将授权令牌应用于请求,谢谢
您在这一行中使用的 RequestTemplate
API 错误:
requestTemplate.header("Authorization: Bearer " + this.jwt);
header
方法接受 2 个参数。首先是一个键,然后是相应的值,还有一个带有 String
可变参数的重载。您的代码会因为 varag 参数而编译,但不会工作,因为它将作为空数组参数处理。
RequestTemplate
中的实现很清楚。如果数组为空,它会认为 header 被删除。
修复很简单,只需将 JWT 令牌放入第二个参数,而不是将其与 header 键连接,如下所示:
requestTemplate.header("Authorization: Bearer ", this.jwt);
我有一个假装客户端的请求拦截器配置,我想验证它是否配置正确。假设向 auth url 发出请求并获得授权。 这似乎工作正常。但我认为它并没有把它放在发送到资源服务器的每个请求中。因此我一直收到 403。但是当我使用我的代码中生成的身份验证令牌在邮递员上尝试此操作时,它工作正常。 下面是代码
@Component
public class FeignC2aSystemOAuthInterceptor implements RequestInterceptor {
@Value("${c2a.oauth2.clientId}")
private String clientId;
@Value("${c2a_system.authUrl}")
private String authUrl;
@Value("${c2a.oauth2.clientSecret}")
private String clientSecret;
private String jwt;
private LocalDateTime expirationDate = LocalDateTime.now();
private final RestTemplate restTemplate;
public FeignC2aSystemOAuthInterceptor(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public void apply(RequestTemplate requestTemplate) {
if (LocalDateTime.now().isAfter(expirationDate)) {
requestToken();
System.out.println("JUST AFTER REQUEST" + this.jwt);
}
/* use the token */
System.out.println("USE THE TOKEN" + this.jwt);
requestTemplate.header("Authorization: Bearer " + this.jwt);
}
private void requestToken() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("client_id", clientId);
map.add("client_secret", clientSecret);
map.add("grant_type", "client_credentials");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<C2AAuthResponse> response = restTemplate.postForEntity(authUrl, request, C2AAuthResponse.class);
this.jwt = Objects.requireNonNull(response.getBody()).getAccessToken();
LocalDateTime localDateTime = LocalDateTime.now();
this.expirationDate = localDateTime.plusSeconds(response.getBody().getExpiresIn());
}
配置
@Configuration
public class FeignC2aSystemConfig {
@Bean
RestTemplate getRestTemplate() {
return new RestTemplate();
};
@Bean
FeignC2aSystemOAuthInterceptor fen () {
return new FeignC2aSystemOAuthInterceptor(getRestTemplate());
}
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
和客户
@FeignClient(name = "c2aSystem", url = "${c2a_system.base_url}", configuration = FeignC2aSystemConfig.class)
public interface C2AApiClient {
@PostMapping(value = C2ASystemIntegrationUrls.SEND, produces = "application/json", consumes = "application/json")
HttpServletResponse sendSms(@RequestBody C2aMessage c2aMessage);
@GetMapping(value = C2ASystemIntegrationUrls.GETLIST, produces = "application/json", consumes = "application/json")
List<MessageData> getMessages();
}
在记录期间,我注意到它调用了拦截器,并且我可以看到使用 sout 记录的身份验证令牌。
我想知道我是否在某个地方弄得一团糟,可能导致它无法将授权令牌应用于请求,谢谢
您在这一行中使用的 RequestTemplate
API 错误:
requestTemplate.header("Authorization: Bearer " + this.jwt);
header
方法接受 2 个参数。首先是一个键,然后是相应的值,还有一个带有 String
可变参数的重载。您的代码会因为 varag 参数而编译,但不会工作,因为它将作为空数组参数处理。
RequestTemplate
中的实现很清楚。如果数组为空,它会认为 header 被删除。
修复很简单,只需将 JWT 令牌放入第二个参数,而不是将其与 header 键连接,如下所示:
requestTemplate.header("Authorization: Bearer ", this.jwt);