首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java SFTP服务器库?

Java SFTP服务器库?
EN

Stack Overflow用户
提问于 2010-06-20 01:08:21
回答 7查看 50.7K关注 0票数 42

有没有可以用来实现SFTP服务器的Java库?

我正在尝试通过SFTP接收文件,但我似乎找不到任何SFTP服务器的实现。我已经找到了FTP/ SFTP /FTPS客户端库和FTP/FTPS服务器库,但没有用于SFTP服务器的库。

为了澄清,我正在尝试通过SFTP接收文件。而不是将文件从我的应用程序“获取”或“放入”到另一个现有的服务器。

现在,我的应用程序允许用户连接到本地linux SFTP服务器,删除文件,然后我的应用程序轮询目录,但我觉得这是一个糟糕的实现;我讨厌“轮询”目录的想法,但不幸的是,他们必须使用SFTP。有什么建议吗?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2012-01-23 23:58:16

如何使用Apache Mina SSHD设置SFTP服务器

代码语言:javascript
复制
public void setupSftpServer(){
    SshServer sshd = SshServer.setUpDefaultServer();
    sshd.setPort(22);
    sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));

    List<NamedFactory<UserAuth>> userAuthFactories = new ArrayList<NamedFactory<UserAuth>>();
    userAuthFactories.add(new UserAuthNone.Factory());
    sshd.setUserAuthFactories(userAuthFactories);

    sshd.setCommandFactory(new ScpCommandFactory());

    List<NamedFactory<Command>> namedFactoryList = new ArrayList<NamedFactory<Command>>();
    namedFactoryList.add(new SftpSubsystem.Factory());
    sshd.setSubsystemFactories(namedFactoryList);

    try {
        sshd.start();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

仅此而已。

票数 50
EN

Stack Overflow用户

发布于 2010-06-20 05:44:09

请注意,SFTP既不是SSL上的FTP,也不是SSH上的FTP。SFTP服务器支持需要在Java中实现SSHD。你最好的选择是Apache SSHD,

http://mina.apache.org/sshd-project/

我从来没有用过SFTP,但我听说它很基本,但很实用。

票数 5
EN

Stack Overflow用户

发布于 2014-04-01 20:00:04

我尝试了在Windows上使用上面的MINA 0.10.1,并修复了一些问题,另外我需要更好的身份验证和PK支持(仍然不推荐用于生产使用):

代码语言:javascript
复制
import java.io.File;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.PrintWriter;

import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
import java.util.Scanner;

import java.math.BigInteger;

import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.interfaces.DSAPublicKey;

import java.security.KeyFactory;

import java.security.spec.KeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.RSAPublicKeySpec;

import org.apache.sshd.common.NamedFactory;

import org.apache.sshd.SshServer;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.PasswordAuthenticator;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.apache.sshd.server.shell.ProcessShellFactory;
import org.apache.sshd.server.UserAuth;
import org.apache.sshd.server.auth.UserAuthPassword;
import org.apache.sshd.server.auth.UserAuthPublicKey;

import org.apache.sshd.common.KeyExchange;
//import org.apache.sshd.server.kex.DHGEX;
//import org.apache.sshd.server.kex.DHGEX256;
import org.apache.sshd.server.kex.ECDHP256;
import org.apache.sshd.server.kex.ECDHP384;
import org.apache.sshd.server.kex.ECDHP521;
import org.apache.sshd.server.kex.DHG1;

import org.apache.mina.util.Base64;
/*
javac -classpath .;lib/sshd-core-0.10.1.jar;lib/mina-core-2.0.7.jar;lib/waffle-jna.jar;lib/guava-13.0.1.jar;lib/jna-platform-4.0.0.jar;lib/jna-4.0.0.jar SFTPServer.java
java -classpath .;lib/sshd-core-0.10.1.jar;lib/slf4j-simple-1.7.6.jar;lib/slf4j-api-1.6.6.jar;lib/mina-core-2.0.7.jar;lib/waffle-jna.jar;lib/guava-13.0.1.jar;lib/jna-platform-4.0.0.jar;lib/jna-4.0.0.jar SFTPServer
*/
public class SFTPServer {
  public void setupSftpServer() throws Exception {

    class AuthorizedKeyEntry {
      private String keyType;
      private String pubKey;

      private byte[] bytes;
      private int pos;
      private PublicKey key = null;

      private int decodeInt() {
        return ((bytes[pos++] & 0xFF) << 24) | ((bytes[pos++] & 0xFF) << 16)
                | ((bytes[pos++] & 0xFF) << 8) | (bytes[pos++] & 0xFF);
      }

      private BigInteger decodeBigInt() {
        int len = decodeInt();
        byte[] bigIntBytes = new byte[len];
        System.arraycopy(bytes, pos, bigIntBytes, 0, len);
        pos += len;
        return new BigInteger(bigIntBytes);
      }

      private void decodeType() {
        int len = decodeInt();
        keyType = new String(bytes, pos, len);
        pos += len;
      }

      public PublicKey getPubKey()  {
        return key;
      }

      public void setPubKey(PublicKey key) throws Exception {
        this.key = key;
        ByteArrayOutputStream byteOs = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(byteOs);
        if (key instanceof RSAPublicKey) {
          keyType = "ssh-rsa";
          dos.writeInt(keyType.getBytes().length);
          dos.write(keyType.getBytes());

          RSAPublicKey rsakey = (RSAPublicKey)key;
          BigInteger e = rsakey.getPublicExponent();
          dos.writeInt(e.toByteArray().length);
          dos.write(e.toByteArray());
          BigInteger m = rsakey.getModulus();
          dos.writeInt(m.toByteArray().length);
          dos.write(m.toByteArray());
        } else if (key instanceof DSAPublicKey) {
          keyType = "ssh-dss";
          dos.writeInt(keyType.getBytes().length);
          dos.write(keyType.getBytes());

          DSAPublicKey dsskey = (DSAPublicKey)key;
          BigInteger p = dsskey.getParams().getP();
          dos.writeInt(p.toByteArray().length);
          dos.write(p.toByteArray());
          BigInteger q = dsskey.getParams().getQ();
          dos.writeInt(q.toByteArray().length);
          dos.write(q.toByteArray());
          BigInteger g = dsskey.getParams().getG();
          dos.writeInt(g.toByteArray().length);
          dos.write(g.toByteArray());
          BigInteger y = dsskey.getY();
          dos.writeInt(y.toByteArray().length);
          dos.write(y.toByteArray());
        } else {
          throw new IllegalArgumentException("unknown key encoding " + key.getAlgorithm());
        }
        bytes = byteOs.toByteArray();
        this.pubKey = new String(Base64.encodeBase64(bytes));
      }

      public void setPubKey(String pubKey) throws Exception {
        this.pubKey = pubKey;
        bytes = Base64.decodeBase64(pubKey.getBytes());
        if (bytes == null)
          return;
        decodeType();
        if (keyType.equals("ssh-rsa")) {
          BigInteger e = decodeBigInt();
          BigInteger m = decodeBigInt();
          KeySpec spec = new RSAPublicKeySpec(m, e);
          key = KeyFactory.getInstance("RSA").generatePublic(spec);
        } else if (keyType.equals("ssh-dss")) {
          BigInteger p = decodeBigInt();
          BigInteger q = decodeBigInt();
          BigInteger g = decodeBigInt();
          BigInteger y = decodeBigInt();
          KeySpec spec = new DSAPublicKeySpec(y, p, q, g);
          key = KeyFactory.getInstance("DSA").generatePublic(spec);
        } else {
          throw new IllegalArgumentException("unknown type " + keyType);
        }
      }
    }

    final SshServer sshd = SshServer.setUpDefaultServer();
    final Map<ServerSession, PublicKey> sessionKeys = new HashMap();

    class AuthorizedKeys extends HashMap<String,AuthorizedKeyEntry> {
      private File file;


      public void load(File file) throws Exception {
        this.file = file;
        Scanner scanner = new Scanner(file).useDelimiter("\n");
        while (scanner.hasNext())
          decodePublicKey(scanner.next());
        scanner.close();
      }

      public void save() throws Exception {
        PrintWriter w = new PrintWriter(file);
        for (String username : keySet()) {
          AuthorizedKeyEntry entry = get(username);
          w.print(entry.keyType + " " + entry.pubKey + " " + username + "\n");
        }
        w.close();
      }

      public void put(String username, PublicKey key) {
        AuthorizedKeyEntry entry = new AuthorizedKeyEntry();
        try {
          entry.setPubKey(key);
        } catch (Exception e) {
          e.printStackTrace();
        }
        super.put(username,entry);
      }

      private void decodePublicKey(String keyLine) throws Exception {
        AuthorizedKeyEntry entry = new AuthorizedKeyEntry();
        String[] toks = keyLine.split(" ");
        String username = toks[toks.length-1];
        for (String part : toks) {
          if (part.startsWith("AAAA")) {
            entry.setPubKey(part);
            //bytes = Base64.decodeBase64(part.getBytes());
            break;
          }
        }
        super.put(username,entry);
      }
    };

    final AuthorizedKeys authenticUserKeys = new AuthorizedKeys(); // load authorized_keys
    File file = new File("authorized_keys");
    file.createNewFile(); // create if not exists
    authenticUserKeys.load(file);


    sshd.setPort(22);
    sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("key.ser"));

    sshd.setShellFactory(new ProcessShellFactory(new String[] { "cmd.exe "}));

    sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
      public boolean authenticate(String username, String password, ServerSession session) {
        boolean authentic = false;
        try {
          new waffle.windows.auth.impl.WindowsAuthProviderImpl().logonUser(username,password);
          authentic = true;
          //authentic = username != null && username.equals(password+password); // obsecurity :)
          if (authentic) {
            PublicKey sessionKey = sessionKeys.get(session);
            if (sessionKey != null)
              authenticUserKeys.put(username, sessionKey); //save entry to authorized_keys
          }
        } catch (Exception e) {
          System.err.println(e);
        }
        return authentic;
      }
    });

    sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
      public boolean authenticate(String username, PublicKey key, ServerSession session) {
        sessionKeys.put(session,key);
        return key.equals(authenticUserKeys.get(username).getPubKey());
      }
    });

    sshd.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(
      new UserAuthPublicKey.Factory()
      ,new UserAuthPassword.Factory()));

    sshd.setCommandFactory(new ScpCommandFactory());

    sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(
      new SftpSubsystem.Factory()));

    //workaround for apache sshd 10.0+ (putty)
    sshd.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList(
      //new DHGEX256.Factory()
      //,new DHGEX.Factory()
      new ECDHP256.Factory()
      ,new ECDHP384.Factory()
      ,new ECDHP521.Factory()
      ,new DHG1.Factory()));

    Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {
        try {
          authenticUserKeys.save();
          System.out.println("Stopping");
          sshd.stop();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });

    System.out.println("Starting");    
    try {
      sshd.start();
      Thread.sleep(Long.MAX_VALUE);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  static public void main(String[] args) throws Exception {
    new SFTPServer().setupSftpServer();
  }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3076443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档