目录

一、SFTP使用场景

二、centos7搭建SFTP

三、Windows搭建

四、java代码连接

 


                                                                                              2018/12/14 杨贤宾 

一、SFTP使用场景

ftp是大多数网站的文件传输选择工具,但ftp并不是非常安全,并且在centos上搭建的vsftpd也非常的不稳定,偶尔会出现权限问题,例如500、或是账号密码不正确等等。

而SFTP是基于默认的22端口,是ssh内含的协议,只要启动了sshd就可以使用。

建议:更高的效率使用FTP协议,更安全的通信使用SFTP协议。

FTP是一种文件传输协议,一般是为了方便数据共享的。包括一个FTP服务器和多个FTP客户端。FTP客户端通过FTP协议在服务器上下载资源。而SFTP协议是在FTP的基础上对数据进行加密,使得传输的数据相对来说更安全。但是这种安全是以牺牲效率为代价的,也就是说SFTP的传输效率比FTP要低(不过现实使用当中,没有发现多大差别)。个人肤浅的认为就是:

  1. FTP要安装,SFTP不要安装。
  2. SFTP更安全,但更安全带来副作用就是的效率比FTP要低些。

二、centos7搭建SFTP

  1. 创建sftp组
    查看组信息
    groupadd sftp
    cat /etc/group

     

  2. 创建一个sftp用户mysftp并加入到创建的sftp组中,同时修改mysftp用户的密码
    useradd -g sftp -s /bin/false mysftp 
    passwd mysftp

     

  3. 新建目录,指定为mysftp用户的主目录
    mkdir -p /sftp/mysftp
    usermod -d /sftp/mysftp mysftp

     

  4. 编辑配置文件/etc/ssh/sshd_config
    将如下这行用#符号注释掉
    # Subsystem      sftp    /usr/libexec/openssh/sftp-server

    并在文件最后面添加如下几行内容然后保存(最好放在文件末尾)
    Subsystem       sftp    internal-sftp   
    Match Group sftp  
    ChrootDirectory /sftp/%u    
    ForceCommand    internal-sftp    
    AllowTcpForwarding no   
    X11Forwarding no  

     

  5. 设置Chroot目录权限
    chown root:sftp /sftp/mysftp  #文件夹所有者必须为root,用户组可以不是root
    chmod 755 /sftp/mysftp   #权限不能超过755,否则会导致登录报错,可以是755

     

  6. 新建一个目录供stp用户mysftp上传文件,这个目录所有者为mysftp所有组为sftp,所有者有写入权限所有组无写入权限
    mkdir /sftp/mysftp/upload  
    chown mysftp:sftp /sftp/mysftp/upload  
    chmod 755 /sftp/mysftp/upload  

     

  7. 关闭selinux并重启sshd服务,然后测试
    setenforce 0
    service sshd restart

     

  8. 在其他服务器上进行验证,sftp 用户名@ip地址
    sftp -P 10001 mysftp@127.0.0.1 

     

三、Windows搭建

  1. 下载安装freesshd

    下载地址:

    http://www.freesshd.com/?ctt=download

    下载后安装,一路点击确认就好,安装时产生key,直接点击确认

  2. 安装软件后,以管理员身份打开
    在ssh中地址可以选在本地地址,端口选在22端口,安装之后可以看到key是默认有的

  3. 新增用户

  4. 更改认证方式
  5. 更改sftp服务器根目录
  6. 启动服务
  7. 如果上一步无法启动,应该是之前已经启动,端口被占用,需要进入服务,重新启动
  8. 下载sftp链接工具(xftp或Filezilla等)
  9. 测试成功
  10. 异常及解决方案
    输入正确用户名和密码提示denied或者key verification failed.,常规解决方案如下
    删除C:\Users\Administrator下的.ssh文件夹,使用管理员程序重新运行freesshd,再次测试连接

四、java代码连接

package com.kehua.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Vector;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException; 

/**
 * 描述: sftp工具类
 * @date 2018年12月11日
 * @author 杨贤宾
 * @version 1.0
 */
public class SFTPUtil {
	private transient Logger log = LoggerFactory.getLogger(this.getClass());  

	private ChannelSftp sftp;  

	private Session session;  
	/** SFTP 登录用户名*/    
	private String username; 
	/** SFTP 登录密码*/    
	private String password;  
	/** 私钥 */    
	private String privateKey;  
	/** SFTP 服务器地址IP地址*/    
	private String host;  
	/** SFTP 端口*/  
	private int port;  


	/**  
	 * 构造基于密码认证的sftp对象  
	 */    
	public SFTPUtil(String username, String password, String host, int port) {  
		this.username = username;  
		this.password = password;  
		this.host = host;  
		this.port = port;  
	} 

	/**  
	 * 构造基于秘钥认证的sftp对象 
	 */  
	public SFTPUtil(String username, String host, int port, String privateKey) {  
		this.username = username;  
		this.host = host;  
		this.port = port;  
		this.privateKey = privateKey;  
	}  

	public SFTPUtil(){}  


	/** 
	 * 连接sftp服务器 
	 */  
	public void login(){  
		try {  
			JSch jsch = new JSch();  
			if (privateKey != null) {  
				jsch.addIdentity(privateKey);// 设置私钥  
			}  

			session = jsch.getSession(username, host, port);  

			if (password != null) {  
				session.setPassword(password);    
			}  
			Properties config = new Properties();  
			config.put("StrictHostKeyChecking", "no");  

			session.setConfig(config);  
			session.connect();  

			Channel channel = session.openChannel("sftp");  
			channel.connect();  

			sftp = (ChannelSftp) channel;  
		} catch (JSchException e) {  
			e.printStackTrace();
		}  
	}    

	/** 
	 * 关闭连接 server  
	 */  
	public void logout(){  
		if (sftp != null) {  
			if (sftp.isConnected()) {  
				sftp.disconnect();  
			}  
		}  
		if (session != null) {  
			if (session.isConnected()) {  
				session.disconnect();  
			}  
		}  
	}  


	/**  
	 * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
	 * @param basePath  服务器的基础路径 
	 * @param directory  上传到该目录  
	 * @param sftpFileName  sftp端文件名  
	 * @param in   输入流  
	 */  
	public void upload(String basePath,String directory, String sftpFileName, InputStream input) throws SftpException{  
		try {   
			sftp.cd(basePath);
			sftp.cd(directory);  
		} catch (SftpException e) { 
			//目录不存在,则创建文件夹
			String [] dirs=directory.split("/");
			String tempPath=basePath;
			for(String dir:dirs){
				if(null== dir || "".equals(dir)) continue;
				tempPath+="/"+dir;
				try{ 
					sftp.cd(tempPath);
				}catch(SftpException ex){
					sftp.mkdir(tempPath);
					sftp.cd(tempPath);
				}
			}
		}  
		sftp.put(input, sftpFileName);  //上传文件
	} 


	/** 
	 * 下载文件。
	 * @param directory 下载目录  
	 * @param downloadFile 下载的文件 
	 * @param saveFile 存在本地的路径 
	 */    
	public void download(String directory, String downloadFile, String saveFile) throws SftpException, FileNotFoundException{  
		if (directory != null && !"".equals(directory)) {  
			sftp.cd(directory);  
		}  
		File file = new File(saveFile);  
		sftp.get(downloadFile, new FileOutputStream(file));  
	}  

	/**  
	 * 下载文件 
	 * @param directory 下载目录 
	 * @param downloadFile 下载的文件名 
	 * @return 字节数组 
	 */  
	public byte[] download(String directory, String downloadFile) throws SftpException, IOException{  
		if (directory != null && !"".equals(directory)) {  
			sftp.cd(directory);  
		}  
		InputStream is = sftp.get(downloadFile);  

		byte[] fileData = IOUtils.toByteArray(is);  

		return fileData;  
	}  


	/** 
	 * 删除文件 
	 * @param directory 要删除文件所在目录 
	 * @param deleteFile 要删除的文件 
	 */  
	public void delete(String directory, String deleteFile) throws SftpException{  
		sftp.cd(directory);  
		sftp.rm(deleteFile);  
	}  


	/** 
	 * 列出目录下的文件 
	 * @param directory 要列出的目录 
	 * @param sftp 
	 */  
	public Vector<?> listFiles(String directory) throws SftpException {  
		return sftp.ls(directory);  
	}  

	
	public static void main(String[] args) throws SftpException, IOException {  
		SFTPUtil sftp = new SFTPUtil("userftp", "khyf3@123", "112.74.59.0", 10001);  
		sftp.login();  
		
		//上传文件测试
		/*File file = new File("E:\\谷歌下载资源\\linux 安装 mysql.html");  
		InputStream is = new FileInputStream(file);  

		sftp.upload("/upload","code", "linux 安装 mysql.html", is);  
		sftp.logout();  */
		
		//下载文件测试
		sftp.download("/upload/code", "CODE_0000000000000020.png" ,"D:\\2.PNG");
		sftp.logout();
	}  
}


 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐