sftp(Secure File Transfer Protocol&SSH File Transfer Protocol)是ssh协议的一部分,
Not to be confused with Simple File Transfer Protocol.
除了速度比ftp慢一些其他和ftp一样,如果对传输信息的安全性要求较高的话sftp是个不错的选择,相比sftp实现ftp要简单的多。
之前我们说sftp是ssh的一部分,这就说明它的功能建立在ssh(身份认证机制)之上,从实现方面来说,我们先要打开channel然后通过该channel发送一个subsystem请求(sftp在ssh软件包中作为一个子系统提供服务):
sendRequest(self, ‘subsystem’, common.NS(‘sftp’), wantReply=1)
之后的比较关键,需要我们在该channel上面创建一个transport并拦截该channel的消息:
client = FileTransferClient()
client.makeConnection(SSHChannel())
SSHChannel().dataReceived = client.dataReceived
sendRequest中requestType相关资料可以查看rfc4254
下面这个例子是google到的,大家可以根据自己的需要对各层进行扩展达到自己想要的效果,当然如果只是想简单的进行transmission这个例子中还有写地方需要修改,例如wantReply和_cbSFTP的callback,当前密码的获取方式等等,所以自己研究吧。
!/usr/bin/env python
from sys import stdout
from twisted.python.log import startLogging, err
from twisted.internet import reactor
from twisted.internet.defer import Deferred
from twisted.conch.ssh.common import NS
from twisted.conch.scripts.cftp import ClientOptions
from twisted.conch.ssh.filetransfer import FileTransferClient
from twisted.conch.client.connect import connect
from twisted.conch.client.default import SSHUserAuthClient, verifyHostKey
from twisted.conch.ssh.connection import SSHConnection
from twisted.conch.ssh.channel import SSHChannel
class SFTPSession(SSHChannel):
name = ‘session’
def channelOpen(self, whatever):
d = self.conn.sendRequest(
self, 'subsystem', NS('sftp'), wantReply=True)
d.addCallbacks(self._cbSFTP)
def _cbSFTP(self, result):
client = FileTransferClient()
client.makeConnection(self)
self.dataReceived = client.dataReceived
self.conn._sftp.callback(client)
class SFTPConnection(SSHConnection):
def serviceStarted(self):
self.openChannel(SFTPSession())
def sftp(user, host, port):
options = ClientOptions()
options[‘host’] = host
options[‘port’] = port
conn = SFTPConnection()
conn._sftp = Deferred()
auth = SSHUserAuthClient(user, options, conn)
connect(host, port, options, verifyHostKey, auth)
return conn._sftp
def transfer(client):
d = client.openFile(‘/opt/sunjianan.txt’, 3, {})
def _watch(result):
print 'result:', result
def cbDir(clientFile):
d = clientFile.readChunk(0, 100)
d.addCallback(_watch)
print 'Made directory'
return d
d.addCallback(cbDir)
return d
def main():
startLogging(stdout)
user = ‘username’
host = ‘localhost’
port = 22
d = sftp(user, host, port)
d.addCallback(transfer)
d.addErrback(err, “Problem with SFTP transfer”)
d.addCallback(lambda ignored: reactor.stop())
reactor.run()
if name == ‘main‘:
main()