欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python使用htpasswd实现基本认证授权的例子

程序员文章站 2022-07-22 18:54:54
前面我讲解了如何将树莓派(raspberry pi)打造成无线路由,感觉每次通过命令ssh管理显麻烦,于是自己动手编写web界面,主要是使用python编写的cgi程序,这...

前面我讲解了如何将树莓派(raspberry pi)打造成无线路由,感觉每次通过命令ssh管理显麻烦,于是自己动手编写web界面,主要是使用python编写的cgi程序,这里用到了mini_httpd这款轻量的web服务器,本来想装nginx的,但是想想还是精简一些吧,毕竟资源有限,况且web管理界面仅我一个人访问。

cgi应用跑起来了,但问题来了,如何实现普通路由的那种打开页面就弹出输入用户名密码的对话框?

Python使用htpasswd实现基本认证授权的例子

这里主要用到http协议的一个知识,那就是http基本认证。

服务器端通过发送类似下面的头信息来实现需要认证请求:

复制代码 代码如下:

http/1.0 401 authorization required
www-authenticate: basic realm="secure area"
content-type: text/html

针对上述要求,于是我在cgi中采用了如下的python代码:
复制代码 代码如下:

def check_login():
    import base64

    if "authorization" in os.environ:
    try:
        cred = base64.b64decode(os.environ['authorization'].split(' ')[1])
        username, password = cred.split(":")
        if db_validate_user(username, password): # 这里匹配数据库用户名密码
        return true
    except:
        pass

    print 'status: 401 unauthorized'
    print 'pragma: no-cache'
    print 'content-type: text/html'
    print 'www-authenticate: basic realm=\"my wireless router\"'
    print
    print """
    <html>
    <head>
        <title>not authenticated</title>
    </head>
    <body>
    <h1>not authenticated.</h1>
    </body>
    </html>"""
    return false

# 调用
if not check_login():
    sys.exit(0)

但是实际操作下来后发现mini_httpd并不转发来自用户的authorization的用户名和密码,也就是说os.environ取不到这个头信息,从而导致认证失败。

经过网上搜索后得知mini_httpd原生支持通过.htpasswd实现简单认证的技术,也就是说我们可以在需要授权访问的目录下建立.htpasswd文件实现,当然这个文件是有格式要求的,我们可以通过htpasswd命令来创建。这个命令一般apache服务器软件会自带,不过mini_httpd也自带了,所以你可以直接使用这个命令。

复制代码 代码如下:

#        建立文件名 账户名 密码
htpasswd -bc .htpasswd admin 123456

当一个目录下有.htpasswd文件时,mini_httpd就会弹出要求用户名和密码的对话框,输入正确后才可以浏览,如果没有这个文件则正常浏览。

因为我的cgi应用是基于python的,所以我希望python能够管理.htpasswd文件,幸好python世界里有现成的库,避免了我们重复造*,使用easy_install的安装方式如下:

复制代码 代码如下:

sudo easy_install htpasswd

官方文档给出的例子如下,感觉操作挺方便的,大家可以试一试:
复制代码 代码如下:

import htpasswd

with htpasswd.basic("/path/to/user.db") as userdb:

    try:
        userdb.add("bob", "password")
    except htpasswd.basic.userexists, e:
        print e
    try:
        userdb.change_password("alice", "newpassword")
    except htpasswd.basic.usernotexists, e:
        print e

with htpasswd.group("/path/to/group.db") as groupdb:

    try:
        groupdb.add_user("bob", "admins")
    except htpasswd.group.useralreadyinagroup, e:
        print e
    try:
        groupdb.delete_user("alice", "managers")
    except htpasswd.group.usernotinagroup, e:
        print e