INT-3935: Add Jsch Proxy Factory Bean

JIRA: https://jira.spring.io/browse/INT-3935
This commit is contained in:
Gary Russell
2016-01-19 16:16:22 -05:00
committed by Artem Bilan
parent c0784bf6ef
commit 62db308c22
4 changed files with 225 additions and 1 deletions

View File

@@ -0,0 +1,90 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.sftp.session;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import com.jcraft.jsch.Proxy;
import com.jcraft.jsch.ProxyHTTP;
import com.jcraft.jsch.ProxySOCKS4;
import com.jcraft.jsch.ProxySOCKS5;
/**
* Spring-friendly factory bean to create Jsch {@link Proxy} objects.
*
* @author Gary Russell
* @since 4.3
*
*/
public class JschProxyFactoryBean extends AbstractFactoryBean<Proxy> {
public enum Type {
HTTP, SOCKS4, SOCKS5
}
private final Type type;
private final String host;
private final int port;
private final String user;
private final String password;
public JschProxyFactoryBean(Type type, String host, int port, String user, String password) {
this.type = type;
this.host = host;
this.port = port;
this.user = user;
this.password = password;
}
@Override
public Class<?> getObjectType() {
switch (this.type) {
case SOCKS5:
return ProxySOCKS5.class;
case SOCKS4:
return ProxySOCKS4.class;
case HTTP:
return ProxyHTTP.class;
default:
throw new UnsupportedOperationException("Invalid type:" + this.type);
}
}
@Override
protected Proxy createInstance() throws Exception {
switch (this.type) {
case SOCKS5:
ProxySOCKS5 socks5proxy = new ProxySOCKS5(this.host, this.port);
socks5proxy.setUserPasswd(this.user, this.password);
return socks5proxy;
case SOCKS4:
ProxySOCKS4 socks4proxy = new ProxySOCKS4(this.host, this.port);
socks4proxy.setUserPasswd(this.user, this.password);
return socks4proxy;
case HTTP:
ProxyHTTP httpProxy = new ProxyHTTP(this.host, this.port);
httpProxy.setUserPasswd(this.user, this.password);
return httpProxy;
default:
throw new UnsupportedOperationException("Invalid type:" + this.type);
}
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.sftp.session;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.integration.test.util.TestUtils;
import com.jcraft.jsch.Proxy;
import com.jcraft.jsch.ProxyHTTP;
import com.jcraft.jsch.ProxySOCKS4;
import com.jcraft.jsch.ProxySOCKS5;
/**
* @author Gary Russell
* @since 4.3
*
*/
public class ProxyTests {
@Test
@Ignore
/*
* Needs host and account
*/
public void testSimpleConnect() {
DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory();
sf.setHost("10.0.0.3");
sf.setPort(22);
sf.setUser("ftptest");
sf.setPassword("ftptest");
sf.setAllowUnknownKeys(true);
sf.getSession().close();
}
@Test
@Ignore
/*
* Needs host and account and...
* $ ssh -D 1080 -f -N gpr@10.0.0.3
*/
public void testProxyConnect() throws Exception {
DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory();
JschProxyFactoryBean proxyFactoryBean = new JschProxyFactoryBean(JschProxyFactoryBean.Type.SOCKS5, "localhost",
1080, "ftptest", "ftptest");
proxyFactoryBean.afterPropertiesSet();
sf.setHost("10.0.0.3");
sf.setPort(22);
sf.setUser("ftptest");
sf.setPassword("ftptest");
sf.setProxy(proxyFactoryBean.getObject());
sf.setAllowUnknownKeys(true);
sf.getSession().close();
}
@Test
public void testFactoryBean() throws Exception {
JschProxyFactoryBean proxyFactoryBean = new JschProxyFactoryBean(JschProxyFactoryBean.Type.SOCKS5, "localhost",
1080, "ftptest", "pass");
proxyFactoryBean.afterPropertiesSet();
Proxy proxy = proxyFactoryBean.getObject();
assertProxy(proxy, ProxySOCKS5.class);
proxyFactoryBean = new JschProxyFactoryBean(JschProxyFactoryBean.Type.SOCKS4, "localhost",
1080, "ftptest", "pass");
proxyFactoryBean.afterPropertiesSet();
proxy = proxyFactoryBean.getObject();
assertProxy(proxy, ProxySOCKS4.class);
proxyFactoryBean = new JschProxyFactoryBean(JschProxyFactoryBean.Type.HTTP, "localhost",
1080, "ftptest", "pass");
proxyFactoryBean.afterPropertiesSet();
proxy = proxyFactoryBean.getObject();
assertProxy(proxy, ProxyHTTP.class);
}
private void assertProxy(Proxy proxy, Class<? extends Proxy> clazz) {
assertThat(proxy, instanceOf(clazz));
assertEquals("ftptest", TestUtils.getPropertyValue(proxy, "user"));
assertEquals("pass", TestUtils.getPropertyValue(proxy, "passwd"));
}
}

View File

@@ -129,7 +129,8 @@ Optional.
*proxy*
Allows for specifying a JSch-based http://epaul.github.com/jsch-documentation/javadoc/com/jcraft/jsch/Proxy.html[Proxy].
If set, then the proxy object is used to create the connection to the remote host.
If set, then the proxy object is used to create the connection to the remote host via the proxy.
See <<sftp-proxy-factory-bean>> for a convenient way to configure the proxy.
*serverAliveCountMax*
@@ -177,6 +178,33 @@ Also see `allowUnknownHosts`.
When a `UserInfo` is provided, the `password` and private key `passphrase` is obtained from it, and discrete
`password` and `privateKeyPassprase` properties cannot be set.
[[sftp-proxy-factory-bean]]
=== Proxy Factory Bean
`Jsch` provides a mechanism to connect to the server via an HTTP or SOCKS proxy.
To use this feature, configure the `Proxy` and provide a reference to the `DefaultSftpSessionFactory` as discussed
above.
Three implementations are provided by `Jsch`, `HTTP`, `SOCKS4` and `SOCKS5`.
_Spring Integration 4.3_ provides a `FactoryBean` making configuration of these proxies easier, allowing property
injection:
[source, xml]
----
<bean id="proxySocks5" class="org.springframework.integration.sftp.session.JschProxyFactoryBean">
<constructor-arg value="SOCKS5" />
<constructor-arg value="${sftp.proxy.address}" />
<constructor-arg value="${sftp.proxy.port}" />
<constructor-arg value="${sftp.proxy.user}" />
<constructor-arg value="${sftp.proxy.pw}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory" >
...
<property name="proxy" ref="proxySocks5" />
...
</bean>
----
[[sftp-dsf]]
=== Delegating Session Factory

View File

@@ -92,3 +92,8 @@ Previously, with requests that had a body (such as `POST`) that had no `content-
With this release, the content type of such requests is considered to be `application/octet-stream` as recommended
by RFC 2616.
See <<http-inbound>> for more information.
==== SFTP Changes
A new factory bean is provided to simplify the configuration of Jsch proxies for SFTP.
See <<sftp-proxy-factory-bean>> for more information.