我有一个连接到Web服务的CXF客户端。此客户端安装在一台机器上,tha在同一网络中有两个IP地址(例如172.16.1.101和172.16.1.102)。
如何将CXF客户端配置为使用特定的源IP地址,以便服务器能够看到来自该特定IP地址的请求,而不是其他请求?
如果我能够访问套接字,我会做如下的事情:
Socket s = new Socket();
s.bind(new InetSocketAddress("172.16.1.102", 0)); //this Ip address is the one I need to specify
s.connect(new InetSocketAddress("google.com", 80));是否可以配置CXF创建的套接字,以便指定源IP地址?
编辑:我需要指定源IP地址,因为在客户端和web服务器之间有一个防火墙,其中一个IP地址有规则(来自其他IP地址的连接被阻塞)。
发布于 2017-04-05 09:00:26
定制的URLStreamHandlerFactory可以工作。
示例:
...
URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() {
@Override
public URLStreamHandler createURLStreamHandler(String protocol) {
if (protocol.equals("http")) {
return new HttpHandler();
} else if (protocol.equals("https")) {
return new sun.net.www.protocol.https.Handler();
}
return null;
}
});
...
private class HttpHandler extends java.net.URLStreamHandler {
protected int getDefaultPort() {
return 80;
}
@Override
protected URLConnection openConnection(URL u) throws IOException {
return openConnection(u, (Proxy) null);
}
@Override
protected URLConnection openConnection(URL u, Proxy p) throws IOException {
return new HttpURLConnection(u, p) {
@Override
protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout)
throws IOException {
return new HttpClient(url, (String) null, -1, true, connectTimeout) {
@Override
protected Socket createSocket() throws IOException {
Socket s = new Socket();
s.bind(new InetSocketAddress(InetAddress.getByName("1.2.3.4"),
0)); // yours IP here
return s;
}
};
}
@Override
protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout,
boolean useCache) throws IOException {
return getNewHttpClient(url, p, connectTimeout);
}
};
}
}对于HTTPS,也可以使用自定义SSLSocketFactory。
HttpsURLConnection.setDefaultSSLSocketFactory(...);发布于 2016-08-03 07:56:05
CXF客户端使用java.net.URLConnection连接到服务。可以将URLConnection配置为以这种方式选择本地IP地址(请参阅如何在java.net.URLConnection上指定本地地址?)
URL url = new URL(yourUrlHere);
Proxy proxy = new Proxy(Proxy.Type.DIRECT,
new InetSocketAddress(
InetAddress.getByAddress(
new byte[]{your, ip, interface, here}), yourTcpPortHere));
URLConnection conn = url.openConnection(proxy);我检查了工件cxf-rt-rs-client和cxf-rt-transports-http的代码,以了解CXF是如何创建连接的。在ProxyFactory中,创建UrlConnection所需的Proxy对象的代码
private Proxy createProxy(final HTTPClientPolicy policy) {
return new Proxy(Proxy.Type.valueOf(policy.getProxyServerType().toString()),
new InetSocketAddress(policy.getProxyServer(),
policy.getProxyServerPort()));
}如您所见,无法配置IP地址,因此我担心问题的答案是--您不能使用CXF配置源IP地址。
但是,我认为修改源代码以允许设置源IP地址并不困难。
HTTPClientPolicy
将以下代码添加到org.apache.cxf.transports.http.configuration.HTTPClientPolicy at cxf-rt-transports-http
public class HTTPClientPolicy {
protected byte[] sourceIPAddress;
protected int port;
public boolean isSetSourceIPAddress(){
return (this.sourceIPAddress != null);
}ProxyFactory
将以下代码修改为org.apache.cxf.transport.http.ProxyFactory at cxf-rt-transports-http
//added || policy.isSetSourceIPAddress()
//getProxy() calls finally to createProxy
public Proxy createProxy(HTTPClientPolicy policy, URI currentUrl) {
if (policy != null) {
// Maybe the user has provided some proxy information
if (policy.isSetProxyServer() || policy.isSetSourceIPAddress())
&& !StringUtils.isEmpty(policy.getProxyServer())) {
return getProxy(policy, currentUrl.getHost());
} else {
// There is a policy but no Proxy configuration,
// fallback on the system proxy configuration
return getSystemProxy(currentUrl.getHost());
}
} else {
// Use system proxy configuration
return getSystemProxy(currentUrl.getHost());
}
}
//Added condition to set the source IP address (is set)
//Will work also with a proxy
private Proxy createProxy(final HTTPClientPolicy policy) {
if (policy.isSetSourceIPAddress()){
Proxy proxy = new Proxy(Proxy.Type.DIRECT,
new InetSocketAddress(
InetAddress.getByAddress(
policy.getSourceIPAddress(), policy.getPort()));
} else {
return new Proxy(Proxy.Type.valueOf(policy.getProxyServerType().toString()),
new InetSocketAddress(policy.getProxyServer(),
policy.getProxyServerPort()));
}
}使用
Client client = ClientProxy.getClient(service);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setSourceIPAddress(new byte[]{your, ip, interface, here}));
httpClientPolicy.setPort(yourTcpPortHere);
http.setClient(httpClientPolicy);发布于 2016-08-01 00:11:40
不确定我是否正确地理解了您的问题,但我不认为您需要在客户机上专门设置一个IP地址,以便服务器读取
Message message = PhaseInterceptorChain.getCurrentMessage();
HttpServletRequest request = (HttpServletRequest)message.get(AbstractHTTPDestination.HTTP_REQUEST);
request.getRemoteAddr()在服务器上添加此代码,它实际上可以从请求中找到IP,您可以在服务器上对IP进行比较。如果这是你要找的,请告诉我。
编辑:?
嗯,我的理解是防火墙没有看到消息头或负载中的IP。它检查原始服务器的IP。
如果我错了,请纠正我,但我觉得如果您将客户端部署在添加了防火墙规则的服务器上,并调用服务器,则没有理由不工作。
让我知道你得到了什么样的错误,比如说堆栈跟踪或者什么的,我们就可以看到发生了什么。
https://stackoverflow.com/questions/38689303
复制相似问题