美文网首页Python入门系列
Python入门系列(十一)——WEB

Python入门系列(十一)——WEB

作者: RabbitMask | 来源:发表于2019-01-28 22:42 被阅读221次

    在渗透行业提及web的话,主要是客户端角度,常见的例子就是爬虫,但为了力求入门,我们简单梳理一下web服务器端,时间关系不做深层拓展。
    一、服务器端
    二、客户端

    一、服务器端

    先来简单梳理下几个概念:

    CGI

    CGI(Common Gateway Interface),通用网关接口,它是一段程序,运行在服务器上如:HTTP服务器,提供同客户端HTML页面的接口,CGI程序可以是Python脚本,PERL脚本,SHELL脚本,C或者C++程序等。它会负责生成动态内容,然后返回给服务器,再由服务器转交给客户端。但在每次产生请求时,服务器都会fork and exec,每次都会有一个新的进程产生,开销较大,基本淘汰。

    WSGI

    (Web Server Gateway Interface),WSGI是作为Web服务器与Web应用程序或应用框架之间的一种低级别的接口,以提升可移植Web应用开发的共同点。WSGI是基于现存的CGI标准而设计的,可以看作是在CGI标准上的一个封装。

    所以、我们在此选择WSGI作为web初步学习,首先选写一个函数用以实现基本逻辑,命名为webdemo

    #webdemo
    def rabbit(env, start_response):
        path = env['PATH_INFO']                     #获取路径参数
        if path == '/rabbit':
            start_response('200 OK', [('Content-Type', 'text/html')])
            body = '<h1>Hello,rabbit!</h1>'
            return [body.encode()]
        if path == '/':
            start_response('200 OK', [('Content-Type', 'text/html')])
            body = '<h1>Hello,But who are U!</h1>'
            return [body.encode()]
        else:
            start_response('200 OK', [('Content-Type', 'text/html')])
            body = '<h1>Sorry,Forget it!</h1>'
            return [body.encode()]
    

    其中,HTTP请求的所有输入信息都可以通过env获得,HTTP响应的输出都可以通过start_response()加上函数返回值作为Body。
    然后再写一个一个服务模块,用以启动WSGI服务,并调用我们刚刚写的处理函数:

    from wsgiref.simple_server import make_server
    from webdemo import rabbit
    
    httpd = make_server('', 8000, rabbit)
    print('Serving HTTP on port 8000...')
    httpd.serve_forever()
    
    #输出:
    Serving HTTP on port 8000...
    127.0.0.1 - - [28/Jan/2019 10:46:01] "GET / HTTP/1.1" 200 29
    127.0.0.1 - - [28/Jan/2019 10:46:01] "GET /favicon.ico HTTP/1.1" 200 25
    127.0.0.1 - - [28/Jan/2019 10:49:42] "GET /rabbit HTTP/1.1" 200 22
    127.0.0.1 - - [28/Jan/2019 10:49:43] "GET /favicon.ico HTTP/1.1" 200 25
    127.0.0.1 - - [28/Jan/2019 10:49:49] "GET /233333 HTTP/1.1" 200 25
    127.0.0.1 - - [28/Jan/2019 10:49:49] "GET /favicon.ico HTTP/1.1" 200 25
    

    其中wsgiref是官方给出的一个实现了WSGI标准用于演示用的简单Python内置库,它实现了一个简单的WSGI Server和WSGI Application(在simple_server模块中),主要分为五个模块:simple_server, util, headers, handlers, validate。

    浏览器

    写到这里,我们遇上了一个新的烦恼,我们这里只是一个简单的响应,如果是复杂响应,再加上上百甚至上千条路径,分布着不同的功能,我们也要通过一层一层的判断它的请求方式、请求路径么?
    所以我们需要在WSGI接口之上能进一步抽象,让我们专注于用一个函数处理一个URL,至于URL到函数的映射以及服务响应问题,就交给Web框架来做。

    于是,就引出了web框架的概念,近些年来随着python排名的飙升,框架也着实不少:CubicWeb,Django,Web2py,Weppy、Zope2、 Bottle,CherryPy,Falcon,Flask,Pyramid,Tornado,Web.py、Wheezy.web……

    作为入门非开发需要,我们选择轻型框架flask简单演示,老规矩,改写上述例子:

    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/', methods=['GET'])
    def home():
        body = '<h1>Hello,But who are U!</h1>'
        return body
    @app.route('/rabbit', methods=['GET'])
    def rabbit():
        body = '<h1>Hello,rabbit!</h1>'
        return body
    @app.errorhandler(404)
    def miss(e):
        body = '<h1>Sorry,Forget it!</h1>'
        return body
    
    if __name__ == '__main__':
        app.run()
    
    #输出:
     * Serving Flask app "flaskdemo" (lazy loading)
     * Environment: production
       WARNING: Do not use the development server in a production environment.
       Use a production WSGI server instead.
     * Debug mode: off
     * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
    127.0.0.1 - - [28/Jan/2019 11:27:17] "GET / HTTP/1.1" 200 -
    127.0.0.1 - - [28/Jan/2019 11:27:21] "GET /rabbit HTTP/1.1" 200 -
    127.0.0.1 - - [28/Jan/2019 11:26:06] "GET /22222 HTTP/1.1" 200 -
    

    省一张截图,跟WSGI结果一致,关于Running on http://127.0.0.1:5000/,Flask默认的Server监听端口为5000。
    但愿没有讲太多,说好不拓展的。其实flask使用的就是装饰器,早在函数章节我们已经详细分析过了。更多其它关于web框架的使用我们在此就不多说了,上述内容也只是为了对python的web服务端形成一个基础性逻辑的认识。

    二、客户端

    urllib、urllib2库为python标准库,用于进行url请求,然而在实际使用中,要面对各种编码问题,所以我们选择自称HTTP for Humans的第三方库requests进行入门学习。
    请求url,无非是为了数据,或者说是便捷享受服务,具象一下无非就是api或者是爬虫等,我们本次以api为例。
    话说,很多网站都是主动提供api的,如百度翻译、地图等服务,以及我们此次用到的站长工具,当然,服务也是付费的,合情合理,同时也表示支持!
    但我们此次不用做商业用途,仅供练习,所以选择了站长工具的IP查询功能进行举例,自行尝试使用burp等抓包工具进行数据包捕获。重放次数过多的话应该会被封IP吧,反正cmd5会的,这完全是为了方便个人使用,懒得开浏览器~

    import requests
    import re
    def ip_adr():
        headers = {'user-agent': 'ceshi/0.0.1'}
        print('本脚本为接口练习使用,\n请勿批量使用。\n退出请输入exit……')
        while True:
            try:
                target_ip = input('请输入目标域名/IP:')
                if target_ip=='exit':
                    break
                r = requests.get('http://ip.tool.chinaz.com/{}'.format(target_ip),headers=headers)
    
                find_adr = re.compile(r'<span class="Whwtdhalf w50-0">.*</span>')
                find_ip = re.compile(r'<span class="Whwtdhalf w15-0">.*</span>')
                res1=find_adr.findall(r.text)
                res2=find_ip.findall(r.text)
                adr=re.findall(r'>.*<',str(res1[1]))
                adr=str(adr)[3:]
                adr=str(adr)[:-3]
                ip=re.findall(r'>.*<',str(res2[4]))
                ip=str(ip)[3:]
                ip=str(ip)[:-3]
                print('目标IP为:{}\n物理地址为:{}'.format(ip,adr))
            except:
                print('您的格式有误,大侠请重新来过~')
    
    if "__main__" == __name__ :
        ip_adr()
    
    #输出:
    本脚本为接口练习使用,
    请勿批量使用。
    退出请输入exit……
    请输入目标域名/IP:www
    您的格式有误,大侠请重新来过~
    请输入目标域名/IP:baidu.com
    目标IP为:123.125.115.110
    物理地址为:北京亦庄联通机房
    请输入目标域名/IP:exit
    
    Process finished with exit code 0
    

    其中url请求由requests模块完成,数据捕获与处理由re模块进行正则匹配。
    既然讲到了这里,我们就尝试一下综合以上所学,将我们的小脚本使用flask布在服务器上!
    首先改写下我们的脚本,用于flask调用,命名为为IpWhere:

    #IpWhere
    import requests
    import re
    
    def ip_adr(target_ip):
        headers = {'user-agent': 'ceshi/0.0.1'}
        r = requests.get('http://ip.tool.chinaz.com/{}'.format(target_ip),headers=headers)
        find_adr = re.compile(r'<span class="Whwtdhalf w50-0">.*</span>')
        find_ip = re.compile(r'<span class="Whwtdhalf w15-0">.*</span>')
        res1=find_adr.findall(r.text)
        res2=find_ip.findall(r.text)
        adr=re.findall(r'>.*<',str(res1[1]))
        adr=str(adr)[3:]
        adr=str(adr)[:-3]
        ip=re.findall(r'>.*<',str(res2[4]))
        ip=str(ip)[3:]
        ip=str(ip)[:-3]
        return '目标IP为:{}\n物理地址为:{}'.format(ip,adr)
    
    if "__main__" == __name__ :
        print(ip_adr('baidu.com'))
    

    服务器端进行flask框架调用:

    from flask import Flask
    from flask import request
    from IpWhere import ip_adr
    
    app = Flask(__name__)
    
    @app.route('/', methods=['GET', 'POST'])
    def home():
        return '''<div align="center">
                  <h1>欢迎来到IP查询系统</h1>
                  <h3>本系统为接口练习使用,请勿批量使用</h3>
                  <form action="/ip" method="get">
                  <p><button type="submit">IP查询系统</button></p>
                  </form>
                  </div>'''
    
    @app.route('/ip', methods=['GET'])
    def ip_form():
        return '''<div align="center">
                  <form action="/ip" method="post">
                  <p><input name="target_ip"></p>
                  <p><button type="submit">查询</button></p>
                  </form>
                  </div>'''
    
    @app.route('/ip', methods=['POST'])
    def ipis():
        try:
            res=ip_adr(request.form['target_ip'])
            return '<div align="center">{}</div>'.format(res)
        except:
            return '<div align="center">再乱输打屎你个瓜娃子!</div>'
    
    
    if __name__ == '__main__':
        app.run()
    
    #输出:
     * Serving Flask app "flaskip" (lazy loading)
     * Environment: production
       WARNING: Do not use the development server in a production environment.
       Use a production WSGI server instead.
     * Debug mode: off
     * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
    127.0.0.1 - - [28/Jan/2019 21:14:43] "GET / HTTP/1.1" 200 -
    127.0.0.1 - - [28/Jan/2019 21:14:48] "GET /ip? HTTP/1.1" 200 -
    127.0.0.1 - - [28/Jan/2019 21:14:52] "GET /ip HTTP/1.1" 200 -
    127.0.0.1 - - [28/Jan/2019 21:15:05] "POST /ip HTTP/1.1" 200 -
    127.0.0.1 - - [28/Jan/2019 21:15:13] "POST /ip HTTP/1.1" 200 -
    

    时间关系,没有进行界面优化,只是做了个简单的button,看下效果:

    效果图

    丑是丑了点>,<,可是效果够啦~
    关于数据处理这一块,如果是某些api返回json文件,可以通过调用json模块进行处理,如果是其它类型,大家可以像这样借助正则匹配或者借助bs4等第三方插件进行处理。
    显然,web方面的应用会是之后的重点,作为基础入门,今天就到这里~

    相关文章

      网友评论

        本文标题:Python入门系列(十一)——WEB

        本文链接:https://www.haomeiwen.com/subject/qdhdjqtx.html