5

我正在寻找一种方法让我的 python 程序通过 pam 处理身份验证。我正在为此使用http://code.google.com/p/web2py/source/browse/gluon/contrib/pam.py,只要我的 python 程序以 root 身份运行,它的效果就很好,这并不理想我的意见。

如何在不需要 root 权限的情况下使用 pam 进行用户名/密码验证?

4

5 回答 5

8

简而言之:使用正确的 Python PAM 实现,正确设置 PAM。

long:在健全的 PAM 设置中,您不需要root特权。最后,这是 PAM 提供的东西之一,权限分离。

pam_unix有办法为您检查密码。似乎(注意,它来自某个 contrib 子目录......)的 PAM 实现web2py没有做正确的事情。也许您的 PAM 设置不正确,如果没有进一步的信息很难判断;这也很大程度上取决于操作系统和风味/分布。

Python 有多个 PAM 绑定(不幸的是,标准库中没有任何内容),请改用这些。对于配置,有大量教程,找到适合您系统的教程。

老/错,不要这样做你不需要是root,你只需要能够阅读/etc/shadow。该文件通常shadow具有只读访问权限的组。因此,您只需在PAM中添加正在运行检查的用户。shadow

groupadd <user> shadow应该做的伎俩。

于 2015-09-06T16:33:12.373 回答
4

最后,我最终使用了 pexpect 并尝试使用 su - username。它有点慢,但效果很好。下面的示例没有经过修饰,但您会明白的。

干杯,

周杰伦

#!/usr/bin/python
import pexpect
def pam(username, password):
        '''Accepts username and password and tried to use PAM for authentication'''
        try:
                child = pexpect.spawn('/bin/su - %s'%(username))
                child.expect('Password:')
                child.sendline(password)
                result=child.expect(['su: Authentication failure',username])
                child.close()
        except Exception as err:
                child.close()
                print ("Error authenticating. Reason: "%(err))
                return False
        if result == 0:
                print ("Authentication failed for user %s."%(username))
                return False
        else:
                print ("Authentication succeeded for user %s."%(username))
                return True

if __name__ == '__main__':
        print pam(username='default',password='chandgeme')
于 2011-03-13T17:05:18.747 回答
4

我认为该pam模块是您的最佳选择,但您不必将其直接嵌入到您的程序中。您可以编写一个简单的服务,该服务绑定到 localhost 上的端口,或侦听 UNIX 域套接字,并为同一主机上的其他进程填充 PAM 请求。然后让您的 web2py 应用程序连接到它以进行用户/密码验证。

例如:

import asyncore
import pam
import socket

class Client(asyncore.dispatcher_with_send):

    def __init__(self, sock):
        asyncore.dispatcher_with_send.__init__(self, sock)
        self._buf = ''

    def handle_read(self):
        data = self._buf + self.recv(1024)
        if not data:
            self.close()
            return
        reqs, data = data.rsplit('\r\n', 1)
        self._buf = data
        for req in reqs.split('\r\n'):
            try:
                user, passwd = req.split()
            except:
                self.send('bad\r\n')
            else:
                if pam.authenticate(user, passwd):
                    self.send('ok\r\n')
                else:
                    self.send('fail\r\n')

    def handle_close(self):
        self.close()


class Service(asyncore.dispatcher_with_send):

    def __init__(self, addr):
        asyncore.dispatcher_with_send.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind(addr)
        self.listen(1)

    def handle_accept(self):
        conn, _ = self.accept()
        Client(conn)

def main():
    addr = ('localhost', 8317)
    Service(addr)
    try:
        asyncore.loop()
    except KeyboardInterrupt:
        pass

if __name__ == '__main__':
    main()

用法:

% telnet localhost 8317
bob abc123
ok
larry badpass
fail
incomplete
bad
于 2011-03-13T03:23:43.680 回答
3

也许python-pam可以为你工作。

于 2016-11-28T12:11:52.803 回答
2

如果您使用他们通常的系统(unix 样式)登录凭据,则不会。在某些时候,PAM 库必须读取只能由 root 读取的影子文件。但是,如果您使用通过替代方法(例如 LDAP 或数据库)进行身份验证的 PAM 配置文件,那么它可以在不需要 root 的情况下工作。

这是我开发自己的框架的原因之一,该框架在不同的用户凭据下运行 URL 路径空间的不同部分。登录部分(仅)可以作为 root 运行以使用 PAM(系统)进行身份验证,其他路径子树处理程序作为不同的用户运行。

我为此使用了PyPAM模块。

于 2011-03-13T17:56:31.040 回答