Python后端技术栈(七)--web框架

2019-07-18 16:24:21 浏览数 (1)

正文共:4722 字 6 图 预计阅读时间:12 分钟

每日分享

Change your thoughts and you change your world.

改变想法,你就改变了你的世界。——诺曼·文森特·皮尔(美国牧师)

小闫语录:

我不缺勤奋,不缺努力,我只是缺少 idea。

1.7 Python web 框架

上篇文章传送门『我是个链接』

上篇文章对数据库中的一些经典问题做了总结,比如关系型数据库中事务、隔离级别、慢查询分析、索引原理以及非关系型数据库的数据结构等等。

本篇文章将开始 Python web 框架的相关内容,开始咯~

1.7.1 Python WSGI 与 web 框架

1.7.1.1 什么是 WSGI ?

我们经常使用 uwsgi/gunicorn 部署 Django/Flask 应用,但是大家思考过一个问题没有,为什么不同的框架可以部署在相同的 web 服务器上呢?比如为什么 Flask/Django 都可以运行在 gunicorn 之上呢?

肯定需要定义一个规范,如果遵守这个规范,就可以让任意的 web 框架运行在相同的 web server 上了。这个规范就是我们提到的 WSGI。也就是 Python Web Server Gateway Interface (PEP3333)

WSGI 出现的意义,官方文档中是这样描述的: This document specifies a proposed standard interface between web servers and Python web applications or frameworks,to promote web application portability across a variety of web servers.

在 WSGI 出现之前,部署 Python 其实有很多种方式,比如 mod_pythonCGIFastCGI等,这样部署会特别的乱,缺乏统一的接口。没有办法将不同的框架部署在任意的服务器上。为了解决这个问题,WSGI 才诞生了。

WSGI 描述了 Web Server(Gunicorn/uWSGI)如何与 web 框架(Flask/Django)交互,Web 框架如何处理请求。

1.7.1.2 WSGI 是如何定义的

其实就是定义了一个可调用对象:

代码语言:javascript复制
def application(environ, start_response):

1. application 就是 WSGI app,一个可调用对象。

2.参数: environ是一个包含 WSGI 环境信息的字典,由 WSGI 服务器提供,常见的 key 有 PATHINFO, QUERYSTRING 等。 start_response是生成 WSGI 响应的回调函数,接收两个参数,status 和 headers。

3.函数返回响应体的迭代器。

我们尝试编写一个兼容 WSGI 的 web 小应用:

代码语言:javascript复制
def mysapp(environ, start_response):
    print(environ['QUERY_STRING'])
    status = '200 OK'
    headers = [('Conent-Type', 'text/html; charset=utf8')]

    start_response(status, headers)
    # 可迭代对象,返回字节
    return [b'<h1>Hello World</h1>']

if __name__ == "__main__":
    from wsgiref.simple_server import make_server
    httpd = make_server('127.0.0.1', 8888, myapp)
    httpd.serve_forever()
1.7.1.3常用的 Python Web 框架对比

Django vs Flask vs Tornado

1.Django:大而全,内置 ORM、Admin 等组件,第三方的插件比较多。

2.Flask:微框架,插件机制,比较灵活。

3.Tornado:异步支持的微框架和异步网络库。

1.7.1.4 什么是MVC?

MVC:模型(Model)、视图(View)、控制器(Controller)

它的出现其实是为了解耦数据、展示和操作。

1.Model:负责业务对象和数据库的交互(ORM)

2.View:负责与用户的交互展示

3.Controller:接收请求参数调用模型和视图完成请求

1.7.1.5 什么是 ORM?

Object Relational Mapping,对象关系映射。它用来实现业务对象与数据表中的字段映射。常见的有 SQLAlchemy、Django ORM 以及最新的 Peewee。优势在于代码更加面向对象,代码量更加的少,灵活性高,提升开发效率。不再关注底层是 MySQL 还是 Oracle 等数据库。缺点就是相比较直接使用 SQL 语句操作数据库来说,有性能损失。

1.7.2 Web 安全

1.7.2.1 什么是 SQL 注入?

通过构造特殊的输入参数传入 Web 应用,导致后端执行了恶意的 SQL,通常是由于程序员未对输入进行过滤,直接动态拼接 SQL 产生。可以使用开源工具 sqlmap,SQLninja 等检查我们的网站是否存在此问题。下面通过一个示例进行演示:

1.首先我们创建一个数据表:

代码语言:javascript复制
create table users(id int not null auto_increment primary key,name varchar(45) default null,email varchar(45) default null,password varchar(45) default null);

2.然后准备测试数据:

代码语言:javascript复制
insert into users (name,email,password) values ('laowang','laowang@qq.com',md5('laowang123'));
insert into users (name,email,password) values ('zhangsan','zhangsan@qq.com',md5('zhangsan123'));
insert into users (name,email,password) values ('lisi','lisi@qq.com',md5('lisi123'));

3.编写 SQL 注入代码:

代码语言:javascript复制
import os
import MySQLdb # pip install mysqlclient

db = MySQLdb.connect(
    host="localhost",
    user="root",
    passwd=os.getenv('MYSQL_PASS')
    db="test"
)
cur = db.cursor()

name = input('Enter name: ')
print('您输入的用户 name 是: {}'.format(name))
password = input('Enter password: ')
print('你输入的密码是: {}'.format(password))
# 直接拼接 sql 参数
sql = "SELECT * FROM users WHERE name='" name "'" " AND password=md5('" password "')"
print(sql)
cur.execute(sql)
for row in cur.fetcall():
    print('查询结果', row)

db.close()

4.我们执行上面的文件,如果输入正确的姓名和密码,可以获取结果。如果输入错误,无法返回。但是有一种情况,输入名字的时候,输入下面的代码:

代码语言:javascript复制
lisi' -- '

在 SQL 中 -- 表示注释

输入上面的代码之后,仍然可以获取正确结果,因为拼接 SQL 之后,注释掉了后面的密码内容。

那么怎么解决呢?可以修改为下面的代码:

代码语言:javascript复制
sql = "SELECT * FROM users WHERE name=%s AND password=md5(%s)"

cur.execute(sql, (name, password))

原理就是 execute 会帮助我们进行一些转义操作,防止 SQL 注入。

1.7.2.2 如何防范 SQL 注入

web 安全一大原则:永远不要相信用户的任何输入

1.对输入参数做好检查(类型和范围);过滤和转义特殊字符

2.不要直接拼接 sql,使用 ORM 可以大大降低 SQL 注入风险

3.数据库层:做好权限管理配置;不要明文存储敏感信息

1.7.2.3 什么是 XSS

XSS(Cross Site Scripting),跨站脚本攻击

也许看见英文你会问,为什么不叫 CSS 呢?如果叫这个你不觉的奇怪吗?这不是层叠样式表吗。

1.恶意用户将代码植入到提供给其他用户使用的页面中,未经转义的恶意代码输出到其他用户的浏览器被执行。

2.用户浏览页面的时候嵌入页面中的脚本(js)会被执行,攻击用户。

3.主要分为两类:反射型(非持久型),存储型(持久型)

反射型就是将可攻击的 js 脚本放到 url 参数里面;存储型的则一般使用评论的方式,后台存储评论之后,其他用户在加载的时候就执行了。

黑客可以收集用户的 document.cookie 发送到指定服务器上,当获取到你的 cookie 之后,它就可以为所欲为了。

1.7.2.4 XSS 危害

XSS 可以利用 js 实现很多危害巨大的操作

1.盗用用户的 cookie,获取敏感信息

2.蠕虫

3.钓鱼

1.7.2.5 什么是 CSRF 攻击

详情请看文章『flask框架中的一些常见问题』

1.7.3 前后端分离与 RESTful

1.7.3.1 什么是前后端分离?有哪些优点?

前后端分离就是后端只负责提供数据接口,不再渲染模板,前端获取数据并呈现。它主要有以下几个优点:

1.前后端解耦,接口复用(前端和客户端公用接口),减少开发量

2.各司其职,前后端同步开发,提升工作效率。定义好接口规范

3.更有利于调试(mock)、测试和和运维部署

1.7.3.2 什么是 RESTful

它的全称是 Representation State Transfer ,中文翻译是表现层状态转移,由 HTTP 协议的主要设计者 Roy Fielding 提出。其中主要有三个概念:资源(Resources)、表现层(Representation)、状态转化(State Transfer)。它是一种以资源为中心的 web 软件架构风格,可以用 Ajax 和 RESTful web 服务构建应用。

1.7.3.3 RESTful 解释

1.Resources(资源):使用 URI 指向的一个实体。比如在 web 应用中,一个用户、一首音乐或者一个订单,我们都可以把它表示为一个实体,称之为资源。

2.Representation(表现层):资源的表现形式,比如图片、HTML 文本等。

3.State Transfer(状态转化):GET/POST/PUT/DELETE/HTTP,动词来操作资源,实现资源状态的改变。

1.7.3.4 RESTful 的准则

设计概念和准则:

1.所有事物抽象为资源(Resources),资源对应唯一的标识(identifier)

2.资源通过接口进行操作实现状态转移,操作本身是无状态的

3.对资源的操作不会改变资源的标识

1.7.3.5 什么是 RESTful API?

它就是 RESTful 风格的 API 接口。

1.通过 HTTP GET/POST/PUT/DELETE 获取/新建/更新/删除 资源

把 HTTP 动词语义和数据库的增删改查结合到一起

2.一般使用 JSON 格式返回数据

3.一般 web 框架都有相应的插件支持 RESTful API

下面我们可以看一下示例:

优质文章推荐:

redis操作命令总结

MySQL相关操作

SQL查询语句

前端中那些让你头疼的英文单词

Flask框架重点知识总结回顾

团队开发注意事项

浅谈密码加密

Django框架中的英文单词

Django中数据库的相关操作

DRF框架中的英文单词

DRF框架

Django相关知识点回顾

python技术面试题-腾讯

0 人点赞