FeignClient出現403錯誤,但是使用OkHttpClient或者curl請求沒有問題。具體報錯為「status 403 reading xxxxx#xxxx(), feign.FeignException$Forbidden: status 403 reading......」


最近在項目中使用FeignClient發https(s)請求的時候發現一個非常奇怪的問題,在上一個文章我寫了將項目中的OkHttpClient替換成FeignClient,這樣能使的代碼好看,易於維護。但是在替換的過程中發現,有一小部分替換之后發不了請求,使用OkHttpClient時可以返回正常的數據,但是使用FeignClient時則提示403,具體的信息如下:

這個是FeignClient的日志:

 這個是錯誤信息:

為了檢查是否由於Cookie或者request header的問題導致的,使用curl命令請求,如下:

上半部分是curl命令,可以發現我只攜帶了一個請求頭「authorization」,其他什么都沒有設置了,也是可以獲得正確的返回值。由於返回的信息部分屬於公司財產,所以打碼比較多,見諒

然后在debug的時候,發現FeignClient使用的是默認的客戶端「feign.client.Default」,我就想切換成「OkHttpClient」,按照網上的教程

  1. 導入依賴
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

  2.  修改配置文件

feign: 
    httpclient: 
        enabled: true

 

 完成上述配置之后重新測試,還是使用的「feign.client.Default」,默認的客戶端。

之后查看FeignClientAutoConfiguration類,部分如下:

也就說在配置了{feign.okhttp.enabled=true}時,還需要判斷當前容器中是否含有OkHttpClient類的對象,如果沒有,則啟動配置類;如果有,則配置類不生效。

所以,既然配置類不生效,那么最簡單暴力的方式就是將「OkHttpFeignConfiguration」里面的信息都拷貝出來,然后自定義一個配置類。

完整的配置類代碼如下:

 

import feign.Client;
import feign.Feign;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory;
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignOkHttpConfig {

    @Bean
    @ConditionalOnMissingBean({Client.class})
    public Client feignClient(okhttp3.OkHttpClient client) {
        return new feign.okhttp.OkHttpClient(client);
    }

    @Bean
    @ConditionalOnMissingBean({ConnectionPool.class})
    public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties, OkHttpClientConnectionPoolFactory connectionPoolFactory) {
        Integer maxTotalConnections = httpClientProperties.getMaxConnections();
        Long timeToLive = httpClientProperties.getTimeToLive();
        TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
        return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);
    }

    @Bean
    public OkHttpClient client(OkHttpClientFactory httpClientFactory, ConnectionPool connectionPool, FeignHttpClientProperties httpClientProperties) {
        Boolean followRedirects = httpClientProperties.isFollowRedirects();
        Integer connectTimeout = httpClientProperties.getConnectionTimeout();
        Boolean disableSslValidation = httpClientProperties.isDisableSslValidation();
        return httpClientFactory.createBuilder(disableSslValidation)
                .connectTimeout((long)connectTimeout, TimeUnit.SECONDS)
                .followRedirects(followRedirects)
                .connectionPool(connectionPool)
                .build();
    }
}

 重啟之后再次測試,成功解決問題。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM