脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|shell|

服务器之家 - 脚本之家 - Python - Python web框架实现增加BasicAuth认证详解

Python web框架实现增加BasicAuth认证详解

2023-05-07 16:24真的不能告诉你我的名字 Python

这篇文章主要为大家详细介绍了Python如何在web框架中实现增加BasicAuth认证,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下

上一篇文章,我们已经为框架定义了【响应对象】,该框架不仅可以获取客户端上传的报文信息,还能生成一些简单信息,如自定义响应头等等。今天我们再次完善一下该框架,给框架增加权限验证的功能,给框架加上一个BasicAuth的方法。

本篇文章所依赖的环境为:

Python web框架实现增加BasicAuth认证详解

本次代码已经放到了gitee上:gitee.com/pdudo/golearn/tree/master/python/webFramework

 

什么是http BashAuth

在日常生活或者工作中,你是否见到过这样的页面呢?

Python web框架实现增加BasicAuth认证详解

当我们打开窗口,网页并不是里面加载出来的,而是弹出了一个输入框,让我们输入其用户名和密码,输入后待服务器验证通过后,才开始展现实际的网页内容。这个就是BashAuth了,全称为: Basic access authentication,也称基本认证。是一种极其简单http协议身份验证方式。BashAuth认证的方式是通过请求头来发送和校验的,而非我们熟知的cookietoken等。

还有一点需要注意,这里所展现的输入框,其实是浏览器底层拆解协议所支持的。

 

BasicAuth认证底层原理

BasicAuth使用的http协议进行身份验证的,所以会将身份信息携带在请求头中进行传输。

第一步: 用户在第一次进行浏览器请求页面的时候,不会携带认证信息,此时服务器接接收信息后,判断报文中请求头没有WWW-Authenticate,此时会返回客户端报文,其中需要将报文响应状态码为401,响应头新增一个keyWWW-Authenticate,值为realm加上请求域,做法是为了避免和其他URL相冲突。所以响应核心报文为:

HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm="pdudo sites"

其中状态码为401代表客户端错误,指的是需要身份验证,WWW-Authenticate响应头的值为Basic realm="pdudo sites"Basic代表验证的模式,realm代表请求域,请求域是为了和其他URL相冲突。

第二步: 当浏览器接收到该报文后,会判断其状态码为401并且请求头中有keyWWW-Authenticate,此时便会弹出输入框,让用户输入信息以便服务器校验。

输入之后,不是直接发送给服务器,而是会根据服务器发送的验证模式进行校验,如basic,加入客户端发送的报文如下:

GET /index HTTP/1.1
HTTP_AUTHORIZATION: Basic cGR1ZG86anVlamlu

其中Get代表请求方式,/index表示请求路径,HTTP/1.1http的版本。请求头HTTP_AUTHORIZATION表示验证数据,Basic是验证方式,cGR1ZG86anVlamlu表示用户名:密码,只不过浏览器使用base64进行编码了而已。

第三步: 服务器在接收到报文后,发现有HTTP_AUTHORIZATION,则会使用base64解码,发现客户端上传的数据为pdudo:juejin,以:为分割,前者是用户名,后则是密码。当验证通过后,进行发送其他信息,若验证未通过,则重复第一步。

Python web框架实现增加BasicAuth认证详解

将BasicAuth认证添加到框架中

我们已经知晓了BasicAuth认证的底层原理,所以可以开始修改我们的框架了,我们将其代码写到上一篇所述的response类中,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def basicAuth(self):
    if "HTTP_AUTHORIZATION" not in self.response:
        return None,None,"HTTP_AUTHORIZATION request header not found"
    else:
        originalVal = self.response["HTTP_AUTHORIZATION"]
        types = originalVal.split(" ")[0]
        values = originalVal.split(" ")[1]
        if types == "Basic":
            userAndPasswd = base64.b64decode(values).decode()
            user = userAndPasswd.split(":")[0]
            passwd = userAndPasswd.split(":")[1]
            return user,passwd,None
        else:
            return None, None, "HTTP_AUTHORIZATION request error,unrecognized type: %s " %(types)

当客户端函数调用basicAuth时,服务器检查客户端http报文中,是否有HTTP_AUTHORIZATION,如果没有,则直接返回HTTP_AUTHORIZATION request header not found

若请求头有该key,则将其抓出来存储到originalVal中,它的值类似于: Basic cGR1ZG86anVlamlu,前者是认证类型,后者是加密后字符串,所以我们需要分开将其取出来,存到typesvalues中,再判断types是否是Basic,如果是我们使用base64进行解密,解密后的值类似于pdudo:juejin,以冒号(:)隔开,前者为用户名,后者为密码,所以我们需要将字符串按照:进行拆分,前者保存到user中,后者保存到passwd中,最后将其数据给函数。

那当第一步检查请求头没有HTTP_AUTHORIZATION或者用户名密码不对,应该如何返回呢? 这个需要用户在函数中进行调用即可,例如:

?
1
2
3
4
5
6
7
8
@myWeb.routes(path="/index",methods="all",regular=False)
def index(r):
    username, password , isok = r.basicAuth()
    if isok != None or username != "pdudo" or password != "juejin":
        r.set_headers("WWW-Authenticate","Basic realm="pdudo sites"")
        r.status_code(401)
        return
    return "123"

上述代码,使用我们自己编写的myWeb框架,定义了一个路由/index,其方法为Get或者Postregular=False则不使用正则路由,在函数中,通过r.basicAuth()来获取客户端上传的用户名密码,当用户名不等于pdudo或者密码不等于juejin或者解析失败的时候,会将响应状态码定义为401,并且设置响应头,keyWWW-Authenticate,值为Basic realm="pdudo sites"

 

框架功能测试

这里就不贴myWeb.py的代码了,太长了,大家可以去gitee上看,这里贴一下main.py代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import myweb
 
@myweb.routes(path="/index",methods="all",regular=False)
 
def index(r):
    username,password,isok = r.basicAuth()
    print("username:",username,"passwd:",password)
    if isok != None or username != "pdudo" or password !="juejin":
        r.set_headers("WWW-Authenticate","Basic realm="pdudo sites"")
        r.status_code(401)
        return
    
     return "123"
 
def main():
    myweb.run("",8888)
 
if __name__ == '__main__':
    main()

为了方便,我将每次获取到的数据,都打印一下,方便待会查看数据。

执行代码后,打开浏览器输入http://pdudo.juejin.cn:8888/index,当弹出框后,我们第一个故意输错,第二次才输正确:

Python web框架实现增加BasicAuth认证详解

我们查看服务器日志,如下:

Python web框架实现增加BasicAuth认证详解

一共收到了3次,第一个输出后,并没有携带报文,被挡回来了,所以用户名和密码都为None,第二次则是密码输入不正确被挡回来了,第三次输入正确,成功得到数据123

 

总结

本篇文章,我们介绍了一个极其古老的认证方式: BashAuth, 它是通过请求头来发送数据和验证的。接着我们了解了一下其认证过程,其中最常用的是类型是Basic,它表示将数据进行base64编码后传输,注意是编码,不是加密。所以在使用该功能的时候,最好配合https使用,以便被抓包后破解。 最后将其添加到我们的web框架myWeb.py中。

到此这篇关于Python web框架实现增加BasicAuth认证详解的文章就介绍到这了,更多相关Python增加BasicAuth认证内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7230084820783824951

延伸 · 阅读

精彩推荐
  • PythonPython 蚁群算法详解

    Python 蚁群算法详解

    这篇文章主要介绍了Python编程实现蚁群算法详解,涉及蚂蚁算法的简介,主要原理及公式,以及Python中的实现代码,具有一定参考价值,需要的朋友可以了...

    王荣胜8722022-01-22
  • Python使用Python程序计算钢琴88个键的音高

    使用Python程序计算钢琴88个键的音高

    这篇文章介绍了使用Python程序计算钢琴88个键的音高,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以...

    雪山飞猪7602022-11-25
  • PythonFlask框架配置与调试操作示例

    Flask框架配置与调试操作示例

    这篇文章主要介绍了Flask框架配置与调试操作,结合实例形式简单分析了flask框架配置管理与调试模式简单操作技巧,需要的朋友可以参考下...

    喷跑的豆子12322021-03-20
  • Pythonpython实现猜数字小游戏

    python实现猜数字小游戏

    这篇文章主要,具有一定的参考价值,感兴趣的小伙伴们可以参考一下介绍了Python实现猜数字小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一...

    雨者9222021-03-07
  • PythonPython函数中的不定长参数相关知识总结

    Python函数中的不定长参数相关知识总结

    今天给大家带来的是关于Python函数的相关知识,文章围绕着Python不定长参数展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下...

    想要飞得更高9902021-12-08
  • Pythonlibreoffice python 操作word及excel文档的方法

    libreoffice python 操作word及excel文档的方法

    这篇文章主要介绍了libreoffice python 操作word及excel文档的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    鸭子船长10352021-08-01
  • PythonPython猫眼电影最近上映的电影票房信息

    Python猫眼电影最近上映的电影票房信息

    这篇文章主要介绍了Python猫眼电影最近上映的电影票房信息,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要...

    嗨学编程5612020-09-19
  • Pythonpython logging 日志轮转文件不删除问题的解决方法

    python logging 日志轮转文件不删除问题的解决方法

    最近在维护项目的python项目代码,项目使用了 python 的日志模块 logging, 设定了保存的日志数目, 不过没有生效,还要通过contab定时清理数据 ...

    脚本之家3182020-09-03