使用Feign配置請(qǐng)求頭以及支持Https協(xié)議
Feign配置請(qǐng)求頭及支持Https協(xié)議
背景
最近跟第三方對(duì)接,請(qǐng)求頭需要特殊處理,同時(shí)是 Https 協(xié)議。
第三方提供的是使用 OkHttp 調(diào)用。同時(shí)呢,使用 OkHttp 封裝了調(diào)用和返回值。
今天對(duì)項(xiàng)目代碼進(jìn)行審查的時(shí)候,想著還是把這個(gè)替換調(diào)吧,實(shí)現(xiàn)起來更加的優(yōu)雅。
Feign配置請(qǐng)求頭
FeignParamsInterceptor 這個(gè)類實(shí)現(xiàn)了 RequestInterceptor ,可以實(shí)現(xiàn)對(duì)請(qǐng)求進(jìn)行攔截處理。
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;?
import java.io.UnsupportedEncodingException;
?
/**
?* @Description feign參數(shù)攔截
?*/
@Component
public class FeignParamsInterceptor implements RequestInterceptor {?
? ? private static final Logger logger = LoggerFactory.getLogger(FeignParamsInterceptor.class);
? ? private static final String loanUrl = "x/";
? ? private static final String accountUrl = "y/";
?
? ? @Value("${xxxx}")
? ? private String clientSecret;
?
? ? @Value("${yyyy}")
? ? private String clientId;
?
? ? @Override
? ? public void apply(RequestTemplate requestTemplate) {
? ? ? ? String url = requestTemplate.url();
? ? ? ? if (url.contains(loanUrl) || url.contains(accountUrl)) {
? ? ? ? ? ? //獲取請(qǐng)求體
? ? ? ? ? ? byte[] body = requestTemplate.body();
? ? ? ? ? ? JSONObject params;
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? params = JSON.parseObject(new String(body, requestTemplate.charset() == null ? "utf-8": requestTemplate.charset().name()));
? ? ? ? ? ? ? ? //設(shè)置請(qǐng)求體
? ? ? ? ? ? ? ? requestTemplate.body(params.toJSONString());
? ? ? ? ? ? ? ? requestTemplate.header("xx", CryptoEncrypt.signBytes(params.toJSONString().getBytes(), clientSecret.getBytes()));
? ? ? ? ? ? ? ? requestTemplate.header("yyyy", clientId);
? ? ? ? ? ? ? ? requestTemplate.header("Content-Type", "application/json;charset=utf-8");
? ? ? ? ? ? } catch (UnsupportedEncodingException e) {
? ? ? ? ? ? ? ? logger.info(e.getMessage(), e);
? ? ? ? ? ? }
? ? ? ? }
? ? }?
}Feign支持Https協(xié)議
如下 FeignHttpsConfig 類內(nèi)容:這個(gè)方案呢,目前是可以實(shí)現(xiàn)效果的。具體的內(nèi)容是否可以簡(jiǎn)化,優(yōu)化。這個(gè)還沒有具體的研究。
本文的解決方案是有問題的。請(qǐng)點(diǎn)擊這里
import feign.Client;
import feign.Feign;
import feign.Logger;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
?
import javax.net.ssl.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
?
@Configuration
public class FeignHttpsConfig {
?
? ? @Bean
? ? public Feign.Builder feignBuilder() {
? ? ? ? final Client trustSSLSockets = client();
? ? ? ? return Feign.builder().client(trustSSLSockets);
? ? }
?
? ? @Bean
? ? public Client client(){
? ? ? ? return new Client.Default(
? ? ? ? ? ? ? ? TrustingSSLSocketFactory.get(), new NoopHostnameVerifier());
? ? }
}
?
class TrustingSSLSocketFactory extends SSLSocketFactory
? ? ? ? implements X509TrustManager, X509KeyManager {
?
? ? private static final Map<String, SSLSocketFactory> sslSocketFactories =
? ? ? ? ? ? new LinkedHashMap<String, SSLSocketFactory>();
? ? private static final char[] KEYSTORE_PASSWORD = "password".toCharArray();
? ? private final static String[] ENABLED_CIPHER_SUITES = {"TLS_RSA_WITH_AES_256_CBC_SHA"};
? ? private final SSLSocketFactory delegate;
? ? private final String serverAlias;
? ? private final PrivateKey privateKey;
? ? private final X509Certificate[] certificateChain;
?
? ? private TrustingSSLSocketFactory(String serverAlias) {
? ? ? ? try {
? ? ? ? ? ? SSLContext sc = SSLContext.getInstance("SSL");
? ? ? ? ? ? sc.init(new KeyManager[] {this}, new TrustManager[] {this}, new SecureRandom());
? ? ? ? ? ? this.delegate = sc.getSocketFactory();
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? throw new RuntimeException(e);
? ? ? ? }
? ? ? ? this.serverAlias = serverAlias;
? ? ? ? if (serverAlias.isEmpty()) {
? ? ? ? ? ? this.privateKey = null;
? ? ? ? ? ? this.certificateChain = null;
? ? ? ? } else {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? KeyStore keyStore =
? ? ? ? ? ? ? ? ? ? ? ? loadKeyStore(TrustingSSLSocketFactory.class.getResourceAsStream("/keystore.jks"));
? ? ? ? ? ? ? ? this.privateKey = (PrivateKey) keyStore.getKey(serverAlias, KEYSTORE_PASSWORD);
? ? ? ? ? ? ? ? Certificate[] rawChain = keyStore.getCertificateChain(serverAlias);
? ? ? ? ? ? ? ? this.certificateChain = Arrays.copyOf(rawChain, rawChain.length, X509Certificate[].class);
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? throw new RuntimeException(e);
? ? ? ? ? ? }
? ? ? ? }
? ? }
?
? ? public static SSLSocketFactory get() {
? ? ? ? return get("");
? ? }
?
? ? public synchronized static SSLSocketFactory get(String serverAlias) {
? ? ? ? if (!sslSocketFactories.containsKey(serverAlias)) {
? ? ? ? ? ? sslSocketFactories.put(serverAlias, new TrustingSSLSocketFactory(serverAlias));
? ? ? ? }
? ? ? ? return sslSocketFactories.get(serverAlias);
? ? }
?
? ? static Socket setEnabledCipherSuites(Socket socket) {
? ? ? ? SSLSocket.class.cast(socket).setEnabledCipherSuites(ENABLED_CIPHER_SUITES);
? ? ? ? return socket;
? ? }
?
? ? private static KeyStore loadKeyStore(InputStream inputStream) throws IOException {
? ? ? ? try {
? ? ? ? ? ? KeyStore keyStore = KeyStore.getInstance("JKS");
? ? ? ? ? ? keyStore.load(inputStream, KEYSTORE_PASSWORD);
? ? ? ? ? ? return keyStore;
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? throw new RuntimeException(e);
? ? ? ? } finally {
? ? ? ? ? ? inputStream.close();
? ? ? ? }
? ? }
?
? ? @Override
? ? public String[] getDefaultCipherSuites() {
? ? ? ? return ENABLED_CIPHER_SUITES;
? ? }
?
? ? @Override
? ? public String[] getSupportedCipherSuites() {
? ? ? ? return ENABLED_CIPHER_SUITES;
? ? }
?
? ? @Override
? ? public Socket createSocket(Socket s, String host, int port, boolean autoClose)
? ? ? ? ? ? throws IOException {
? ? ? ? return setEnabledCipherSuites(delegate.createSocket(s, host, port, autoClose));
? ? }
?
? ? @Override
? ? public Socket createSocket(String host, int port) throws IOException {
? ? ? ? return setEnabledCipherSuites(delegate.createSocket(host, port));
? ? }
?
? ? @Override
? ? public Socket createSocket(InetAddress host, int port) throws IOException {
? ? ? ? return setEnabledCipherSuites(delegate.createSocket(host, port));
? ? }
?
? ? @Override
? ? public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
? ? ? ? ? ? throws IOException {
? ? ? ? return setEnabledCipherSuites(delegate.createSocket(host, port, localHost, localPort));
? ? }
?
? ? @Override
? ? public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
? ? ? ? ? ? throws IOException {
? ? ? ? return setEnabledCipherSuites(delegate.createSocket(address, port, localAddress, localPort));
? ? }
?
? ? @Override
? ? public X509Certificate[] getAcceptedIssuers() {
? ? ? ? return null;
? ? }
?
? ? @Override
? ? public void checkClientTrusted(X509Certificate[] certs, String authType) {}
?
? ? @Override
? ? public void checkServerTrusted(X509Certificate[] certs, String authType) {}
?
? ? @Override
? ? public String[] getClientAliases(String keyType, Principal[] issuers) {
? ? ? ? return null;
? ? }
?
? ? @Override
? ? public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
? ? ? ? return null;
? ? }
?
? ? @Override
? ? public String[] getServerAliases(String keyType, Principal[] issuers) {
? ? ? ? return null;
? ? }
?
? ? @Override
? ? public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
? ? ? ? return serverAlias;
? ? }
?
? ? @Override
? ? public X509Certificate[] getCertificateChain(String alias) {
? ? ? ? return certificateChain;
? ? }
?
? ? @Override
? ? public PrivateKey getPrivateKey(String alias) {
? ? ? ? return privateKey;
? ? }??
}Feign client 設(shè)置請(qǐng)求頭信息
Feign client端
@FeignClient(url = "${test.url}", name = "cclient",configuration= ClientConfiguration.class,fallback = APIClientFallback.class)
public interface APIClient {?? ??? ?
?? ?
?? ?@RequestMapping(method = RequestMethod.POST, value = "/check/test")
?? ?String checkResult(@RequestParam("sendTelNo") String sendTelNo,@RequestParam("certType") String certType,@RequestParam("certCode") String certCode,@RequestParam("userName") String userName);
?? ?
?? ?@RequestMapping(method = RequestMethod.POST, value = "/userstaus/test")
?? ?String inusetime(@RequestParam("sendTelNo") String sendTelNo);?? ?
?? ?
?? ?@RequestMapping(method = RequestMethod.POST, value = "/userstaus/test")
?? ?String offnetIdentify(@RequestParam("sendTelNo") String sendTelNo,@RequestParam("date") String date);配置文件 application-dev.yml
test: ? ? ? url: https://xxxxxx:8243/test ? ? ? tokenId: 11111112222222?
feign configuration 這里配置全局的請(qǐng)求頭和token
@Configuration
public class ClientConfiguration {
?? ?
?? ?@Value("${test.tokenId}")
?? ?private String tokenId;
?? ?
?? ?@Bean
? ? public RequestInterceptor headerInterceptor() {
?? ??? ?return new RequestInterceptor(){
?? ??? ??? ?@Override
?? ??? ??? ?public void apply(RequestTemplate template) {
?? ??? ??? ??? ?List<String> authorizationList = Lists.newArrayList("Bearer "+tokenId);
?? ??? ??? ??? ?List<String> contentTypeList = Lists.newArrayList("application/x-www-form-urlencoded;charset=utf-8");
?? ??? ??? ??? ?Map<String, Collection<String>> headers =ImmutableMap.of("Authorization", authorizationList,"Content-Type", contentTypeList);
?? ??? ??? ??? ?template.headers(headers);
?? ??? ??? ?}
?? ??? ?};
?? ?}feign 異常處理
@Component
public class APIClientFallback implements APIClient{
?? ?@Override
?? ?public String checkResult(String sendTelNo, String certType, String certCode, String userName) {
?? ??? ?return toJsonString();
?? ?}
?? ?@Override
?? ?public String inusetime(String sendTelNo) {
?? ??? ?return toJsonString();
?? ?}
?? ?@Override
?? ?public String offnetIdentify(String sendTelNo, String date) {
?? ??? ?return toJsonString();
?? ?}
?? ?private String toJsonString() {
?? ??? ?BaseResult resultVo = new BaseResult();
?? ??? ?resultVo.renderStatus(ResultTypeEnum.SERVICE_ERROR);
?? ??? ?ObjectMapper mapper = new ObjectMapper();
?? ??? ?try {
?? ??? ??? ?return mapper.writeValueAsString(resultVo);
?? ??? ?} catch (JsonProcessingException e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ?}
?? ??? ?return null;
?? ?}
}以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Nexus使用nginx代理實(shí)現(xiàn)支持HTTPS協(xié)議
- Spring Boot項(xiàng)目如何同時(shí)支持HTTP和HTTPS協(xié)議的實(shí)現(xiàn)
- Spring Boot應(yīng)用程序同時(shí)支持HTTP和HTTPS協(xié)議的實(shí)現(xiàn)方法
- SpringBoot2.0如何啟用https協(xié)議
- 關(guān)于Https協(xié)議和HttpClient的實(shí)現(xiàn)詳解
- startssl申請(qǐng)SSL證書 并且配置 iis 啟用https協(xié)議
- Java獲取http和https協(xié)議返回的json數(shù)據(jù)
- Linux下nginx配置https協(xié)議訪問的方法
- iOS9蘋果將原h(huán)ttp協(xié)議改成了https協(xié)議的方法
- apache中使用mod_gnutls模塊實(shí)現(xiàn)多個(gè)SSL站點(diǎn)配置(多個(gè)HTTPS協(xié)議的虛擬主機(jī))
- https協(xié)議詳解
相關(guān)文章
Java根據(jù)控制臺(tái)實(shí)現(xiàn)定位異常
這篇文章主要介紹了Java根據(jù)控制臺(tái)定位異常,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
IDEA 單元測(cè)試創(chuàng)建方法詳解(2020.03版本親測(cè))
這篇文章主要介紹了IDEA 單元測(cè)試創(chuàng)建方法詳解(2020.03版本親測(cè)),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
Spring?BeanDefinition父子關(guān)系示例解析
這篇文章主要為大家介紹了Spring?BeanDefinition父子關(guān)系示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
Java中RabbitMQ消息隊(duì)列的交換機(jī)詳解
這篇文章主要介紹了Java中的RabbitMQ交換機(jī)詳解,消息隊(duì)列是指利用高效可靠的消息傳遞機(jī)制進(jìn)行與平臺(tái)無關(guān)的數(shù)據(jù)交流,并基于數(shù)據(jù)通信來進(jìn)行分布式系統(tǒng)的集成,是在消息的傳輸過程中保存消息的容器,需要的朋友可以參考下2023-07-07
關(guān)于@Scheduled不執(zhí)行的原因分析
這篇文章主要介紹了關(guān)于@Scheduled不執(zhí)行的原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Java使用Hutool實(shí)現(xiàn)AES、DES加密解密的方法
本篇文章主要介紹了Java使用Hutool實(shí)現(xiàn)AES、DES加密解密的方法,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08
Spring使用注解進(jìn)行對(duì)象裝配(DI)的操作
獲取Bean對(duì)象也叫做對(duì)象裝配,就是把對(duì)象取出來放到某個(gè)類中,有時(shí)候也叫對(duì)象注入,這篇文章主要介紹了Spring使用注解進(jìn)行對(duì)象裝配(DI),需要的朋友可以參考下2023-07-07

