关于python:paramiko允许没有密钥的sftp连接

paramiko allows sftp connection without key

我当时正在运行paramiko github中demo文件夹中的demo sftp.py文件。我在pydev中逐步完成了它,并期望得到一个错误,因为我没有一个要连接的服务器的密钥,但是我得到了print语句,它说脚本无法打开主机密钥文件,然后它继续执行并执行了get和put。

这是一个代码片段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
try:
    host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
except IOError:
    try:
        # try ~/ssh/ too, because windows can't have a folder named ~/.ssh/
        host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts'))
    except IOError:
        print '*** Unable to open host keys file'
        host_keys = {}

if host_keys.has_key(hostname):
    hostkeytype = host_keys[hostname].keys()[0]
    hostkey = host_keys[hostname][hostkeytype]
    print 'Using host key of type %s' % hostkeytype


# now, connect and use paramiko Transport to negotiate SSH2 across the connection
try:
    t = paramiko.Transport((hostname, port))
    t.connect(username=username, password=password, hostkey=hostkey)
    sftp = paramiko.SFTPClient.from_transport(t)

    # dirlist on remote host
    dirlist = sftp.listdir('.')
    print"Dirlist:", dirlist

我真的以为它会转到t.connect线上的except,因为hostkey不是类型。

当我打开与

1
2
3
4
5
6
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        ssh.connect('.'.join([self.name, self.domain]),
                    username=self.username, password=self.password)
        stdin, stdout, stderr = ssh.exec_command("ps aux | grep Xvnc | wc -l")

我必须使用autoaddpolicy()行,否则会失败。那有什么区别呢?显然,我只是在学习这个,但我认为sftp和ssh一样严格。


看起来这是一种可以接受的做法。

来自transport.connect的注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
'''
Negotiate an SSH2 session, and optionally verify the server's host key
and authenticate using a password or private key.  This is a shortcut
for L{start_client}, L{get_remote_server_key}, and
L{Transport.auth_password} or L{Transport.auth_publickey}.  Use those
methods if you want more control.

You can use this method immediately after creating a Transport to
negotiate encryption with a server.  If it fails, an exception will be
thrown.  On success, the method will return cleanly, and an encrypted
session exists.  You may immediately call L{open_channel} or
L{open_session} to get a L{Channel} object, which is used for data
transfer.

@note: If you fail to supply a password or private key, this method may
succeed, but a subsequent L{open_channel} or L{open_session} call may
fail because you haven't authenticated yet.
'''

sshclient.connect的注释

1
2
3
4
5
6
7
8
'''
Connect to an SSH server and authenticate to it.  The server's host key
is checked against the system host keys (see L{load_system_host_keys})
and any local host keys (L{load_host_keys}).  If the server's hostname
is not found in either set of host keys, the missing host key policy
is used (see L{set_missing_host_key_policy}).  The default policy is
to reject the key and raise an L{SSHException}.
'''

可能是因为sftp只能传输数据,而ssh可以运行终端命令。我发现有趣的是,一个处于中间位置的人似乎并不关心。