- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想在我们的应用程序中为两个 JAX-WS/RS 客户端实现 CXF 的故障转移功能,这些客户端必须使用客户端证书通过 HTTPS 调用远程 Web 服务。已部署 2 个远程服务器:主服务器 + 备用服务器。
我有点迷失如何在故障转移发生后保证相同的功能(使用正确的 TLS 参数/SSL session )。
JAX-WS 客户端
有6个ClientServices扩展AbstractClientServiceImpl
并使用相同的PortType wsClient
bean和远程服务器的相同basePath,但是它们设置了要调用的服务的最后一个uri部分使用自己的 String getEndpointUrl(){ return "X";}
方法。
BasePath: https://remote1.server.com:443/api
Alternate addresses: https://remote2.server.com:443/api
请看一下代码 - ClientEndpointAddressInterceptor
。使用此拦截器,我可以组合 basePath + lastUriPart 并为特定 ClientService 调用正确的目标端点 - 即使发生故障转移也是如此。例如:
target endpoint for ClientService1.class https://remote1.server.com:443/api/service1
target endpoint for ClientService2.class: https://remote1.server.com:443/api/service2
两周来我一直在努力寻找正确的设置/配置。如果我不像这样将 tlsClientParameters 或 HttpClientPolicy 添加到扩展程序,那么在进行故障转移后,我将无法看到新创建的任何 TLS 设置导管!
// ssl settings
endpointInfo.addExtensor(tlsClientParameters);
我不知道这是否是正确的方法,但是通过这种狡猾的解决方法,我可以设法为 2 个远程调用“提供”相同的 tlsClientParams(主要 +备用远程服务器地址)- 客户端证书的 SAN 具有两个服务器的 DNS 名称。
技术:SpringBoot v2.1 + CXF 3.3.0 + Tomcat8.5
@Bean
public PortType wsClient(Properties properties,
TLSClientParameters tlsClientParameters,
LoggingFeature loggingFeature,
ClientEndpointAddressFeature clientEndpointAddressFeature) {
return createClient(properties, huTlsClientParameters, loggingFeature,
createFailoverFeature(properties.getFailover().getAddresses(), properties.getFailover().getRetryDelay()),
clientEndpointAddressFeature);
}
private FailoverFeature createFailoverFeature(String[] alternateAddresses, long failOverRetryDelay) {
final FailoverFeature failOverFeature = new FailoverFeature();
final SequentialStrategy strategy = new SequentialStrategy();
strategy.setAlternateAddresses(Arrays.asList(alternateAddresses));
strategy.setDelayBetweenRetries(failOverRetryDelay);
failOverFeature.setStrategy(strategy);
return failOverFeature;
}
private PortType createClient(Properties properties, TLSClientParameters tlsClientParameters, WebServiceFeature... features) {
final Service service = new Service();
final PortType client = service.getPortType(features);
final Client clientProxy = ClientProxy.getClient(client);
final EndpointInfo endpointInfo = clientProxy.getEndpoint().getEndpointInfo();
final HTTPClientPolicy httpClientPolicy = Optional.ofNullable(endpointInfo.getExtensor(HTTPClientPolicy.class))
.orElseGet(() -> {
// if there is no XYFeature, policy has to be initialized at this point
final HTTPClientPolicy policy = new HTTPClientPolicy();
policy.setAccept(HuHttpHeaders.HEADER_ACCEPT_VALUE);
endpointInfo.addExtensor(policy);
return policy;
});
// timeout settings
httpClientPolicy.setConnectionTimeout(properties.getConnectionTimeout());
httpClientPolicy.setReceiveTimeout(properties.getReadTimeout());
// set content-length by default
httpClientPolicy.setAllowChunking(false);
// ssl settings
endpointInfo.addExtensor(tlsClientParameters);
// set global requestContext
setRequestContext((BindingProvider) client, properties.getUrl());
return client;
}
private void setRequestContext(BindingProvider bp, String server) {
bp.getRequestContext().put(Message.ENDPOINT_ADDRESS, server);
bp.getRequestContext().put(ClientImpl.THREAD_LOCAL_REQUEST_CONTEXT, true);
bp.getRequestContext().put(Message.SCHEMA_VALIDATION_ENABLED, true);
bp.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, true);
}
public class ClientEndpointAddressOutInterceptor extends AbstractPhaseInterceptor<Message> {
public ClientEndpointAddressOutInterceptor() {
super(Phase.PREPARE_SEND);
addBefore(MessageSenderInterceptor.class.getName());
}
@Override
public void handleMessage(Message message) throws Fault {
final String previousEndpointAddress = (String) message.get(Message.ENDPOINT_ADDRESS);
final String lastUriPath = (String) message.get("lastUriPath");
message.put(Message.ENDPOINT_ADDRESS, previousEndpointAddress + lastUriPath);
}
}
public abstract class AbstractClientServiceImpl implements ClientService {
public AbstractClientServiceImpl(PortType PortType) {
this.portType = portType;
}
@Override
public HttpStatus sendRequest(String xmlData) {
...
final BindingProvider bindingProvider = (BindingProvider) this.portType;
try {
// set http header for this particular request
// also store bindingProvider.getRequestContext().put("lastUriPath", getEndpointUrl());
HttpHeaderUtil.setHttpHeader(getSoapActionUrl(), bindingProvider, getEndpointUrl());
execute(xmlData, createSoapHeader());
} catch (Exception ex) {
...
}
...
}
// last uri part
protected abstract String getEndpointUrl();
// execute is responsible for calling a particular service. e.g: in ClientService1.class portType.callService1(xmlData);
protected abstract void execute(String xmlData, TransactionHeader transactionHeader);
}
问题
JAX-WS 客户端
JAX-RS 客户端
实际上,上面针对 JAX-WS 客户端解决了同样的 2 个关注点/问题。
唯一的区别是 RS 有 3 个客户端调用方法,使用声明为 的相同客户端实例
private WebClient webClient(){
final JAXRSClientFactoryBean clientFactoryBean = new JAXRSClientFactoryBean();
clientFactoryBean.setThreadSafe(true);
final WebClient webClient = clientFactoryBean.createWebClient();
final ClientConfiguration config = WebClient.getConfig(webClient);
config.getRequestContext().put(HTTPConduit.NO_IO_EXCEPTIONS, Boolean.TRUE);
// ssl settings
config.getEndpoint().getEndpointInfo().addExtensor(tlsClientParameters);
return webClient;
}
感谢您提前提供的帮助。
最佳答案
解决方案是使用 CXF 的 HTTPConduitConfigurator,详细信息如下:https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=49941#ClientHTTPTransport(includingSSLsupport)-HowtouseHTTPConduitConfigurer ?
HTTPConduitConfigurer httpConduitConfigurer = new HTTPConduitConfigurer() {
public void configure(String name, String address, HTTPConduit c) {
c.setTlsClientParameters(_tlsParams);
}
}
bus.setExtension(httpConduitConfigurer, HTTPConduitConfigurer.class);
这将在创建的所有管道上设置 TLS 客户端参数,例如使用故障转移时。
关于java - CXF 故障转移管道即时修改 - 保证相同的 SSL session 和客户端线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56658741/
是 if(a == 0 && b == 0 && c == 0) { return; } 一样 if(a == 0) { return; } if(b == 0) { return; } if(c =
我想做这样的事情: Class A Class B extends A Class C extends A B b = new B(); C c = new C(); b->setField("foo
我对 Mysql 世界很天真......:)我试图使用连接从表中查询, 我遇到结果集问题...表结构如下 下面... VIDEO_XXXXX | Field | Type
我最近问过关于从另一个类获取类的唯一实例的问题。 ( How to get specific instance of class from another class in Java? ) 所以,我正
假设我们有两种类型 using t1 = int*; using t2 = int*; 我知道 std::is_same::value会给我们true .什么是,或者是否有模板工具可以实现以下目标?
对于我的一个应用程序,我假设比较 2 个字符串的第一个字符比比较整个字符串是否相等要快。例如,如果我知道只有 2 个可能的字符串(在一组 n 字符串中)可以以相同的字母开头(比如说 'q'),如果是这
我想在我的NXP LPC11U37H主板(ARM Cortex-M0)上分析一些算法,因为我想知道执行特定算法需要多少个时钟周期。 我编写了这些简单的宏来进行一些分析: #define START_C
我在 Excel 中创建了一个宏,它将在 Excel 中复制一个表格,并将行除以我确定的特定数字(默认 = 500 行),并为宏创建的每个部门打开不同的工作表。 使用的代码是这样的: Sub Copy
我想根据第一个字典对第二个字典的值求和。如果我有字典 A 和 B。 A = {"Mark": ["a", "b", "c", "d"], "June": ["e", "a"], "John": ["a
当我这样做时 system()在 Perl 中调用,我通常根据 perldocs 检查返回码.嗯,我是这么想的。大部分时间 $rc!=0对我来说已经足够了。最近我在这里帮助了两个遇到问题的人syste
在我的进度条上,我试图让它检测 div 加载速度。 如果 div 加载速度很快,我想要实现的目标将很快达到 100%。但进度条的加载速度应该与 div 的加载速度一样快。 问题:如何让我的进度条加载
当我获得与本地时间相同的时间戳时,firebase 生成的服务器时间戳是否会自动转换为本地时间,或者我错过了什么? _firestore.collection("9213903123").docume
根据the original OWL definition of OWL DL ,我们不能为类和个体赋予相同的名称(这是 OWL DL 和 OWL Full 之间的明显区别)。 "Punning" i
我有两个输入复选框: 尝试使用 jQuery 来允许两个输入的行为相同。如果选中第一个复选框,则选中第二个复选框。如果未检查第 1 个,则不会检查第 2 个。反之亦然。 我有代码: $('inpu
可以从不同系统编译两个相同的java文件,但它们都有相同的内容操作系统(Windows 7),会生成不同的.class文件(大小)? 最佳答案 是的,您可以检查是否有不同版本的JDK(Java Dev
我正在清理另一个人的正则表达式,他们目前所有的都以结尾 .*$ 那么下面的不是完全一样吗? .* 最佳答案 .*将尽可能匹配,但默认情况下为 .不匹配换行符。如果您要匹配的文本有换行符并且您处于 MU
我使用 Pick ,但是如何编写可以选择多个字段的通用PickMulti呢? interface MyInterface { a: number, b: number, c: number
我有一个 SQL 数据库服务器和 2 个具有相同结构和数据的数据库。我在 2 个数据库中运行相同的 sql 查询,其中一个需要更长的时间,而另一个在不到 50% 的时间内完成。他们都有不同的执行计划。
我需要你的帮助,我有一个包含两列的表,一个 id 和 numpos,我希望 id 和 numops 具有相同的结果。 例子: $cnx = mysql_connect( "localhost", "r
如何将相同的列(在本例中按“级别”排序)放在一起?我正在做一个高分,我从我的数据库中按级别列出它们。如果他们处于同一级别,我希望他们具有相同的 ID。 但是我不想在别人身上显示ID。只有第一个。这是一
我是一名优秀的程序员,十分优秀!