Python Web 面试题

1 Web 相关

get 和 post 区别

  • get

    • 请求数据在 URL 末尾,URL 长度有限制

    • 请求幂等,即无论请求多少次,服务器响应始终相同,这是因为 get 至少获取资源,而不修改资源

    • 可以被浏览器缓存,以便以后的请求中更快地获取相同资源

    • 可以在浏览器中输入或作为超链接点击

  • post

    • 参数在请求体中,可以传递更多数据

    • 不幂等,因为通常需要修改或创建资源

    • 无法被浏览器缓存,因为可能会修改服务器资源

    • 请求必须通过表单或 js 发送

cookies 和 session 的区别,cookie 的安全性

都是用于 web 开发中用于跟踪用户状态的技术,区别如下:

  1. 存储位置:Cookie 存储在客户端浏览器小文件中,Session 是存储在服务器端的内存或数据库中

  2. 存储内容:Cookie 中存储的是客户端的一些状态信息,例如用户的登录状态、语言偏好等;而 Session 中存储的是服务器端保存的用户状态信息,例如用户 ID、购物车内容等。

  3. 安全性:Cookie 因为存储在浏览器,容易被攻击,Session 存储在服务器端,安全性更高

  4. 有效期:Cookie 可以设置一个过期时间,当超过这个时间后,Cookie 将自动失效,而 Session 可以根据需要设置过期时间或者在用户关闭浏览器时自动过期

综上所述,Cookie 和 Session 都是用于跟踪用户状态的技术,但存储位置、存储内容、安全性和有效期等方面有所不同。在实际开发中,应该根据具体需求选择合适的技术。例如,对于需要跨多个页面和多个设备保存用户状态的应用程序,应该使用 Cookie;而对于需要保存更多用户状态信息和更高安全性要求的应用程序,应该使用 Session。

jwt token 和 session 的区别

JWT (JSON Web Token) 和 Session 都是用于认证和授权的技术,它们之间的区别如下:

  • 数据存储:Session 是在服务器端存储用户状态信息的一种方式,通常使用内存或数据库来存储 Session 数据;而 JWT 是一种无状态的认证方式,Token 数据是通过编码后存储在客户端的 Cookie 或 LocalStorage 中,服务器不会存储 Token 数据。

  • 跨域支持:由于 Session 是基于 Cookie 实现的,因此在跨域请求时需要特殊处理;而 JWT 则可以在不同域名之间共享,因为 Token 数据是存储在客户端的。

  • 扩展性:JWT 可以扩展为不同的认证方式,例如基于 OAuth 的认证方式;而 Session 的扩展性相对较弱,需要在服务器端进行实现。

  • 安全性:使用 Session 进行认证时,需要确保 Session ID 的安全,否则可能会被攻击者盗取;而使用 JWT 进行认证时,可以使用加密算法对 Token 数据进行加密,提高安全性。

  • 无状态性:由于 JWT 是无状态的,因此可以避免服务器端的负载问题,特别适合于分布式系统和微服务架构。

总的来说,JWT 适合于分布式系统和无状态应用,而 Session 适合于传统的 Web 应用。使用哪种方式,取决于具体的需求和应用场景。

docker 镜像和容器的区别

Docker是一种用于构建和管理应用程序的开源平台。在Docker中,镜像和容器是两个重要的概念。

  • Docker镜像是应用程序的打包和分发方式。它包含了应用程序所需的所有文件、配置和依赖项,可以看作是一个轻量级的虚拟机模板。Docker镜像是只读的,一旦创建就不能更改。镜像通常是由Dockerfile文件定义的,Dockerfile文件是一种文本文件,用于指定构建Docker镜像所需的所有步骤。

  • Docker容器是Docker镜像的运行实例。容器是可运行的、独立的应用程序单元,可以在任何支持Docker的环境中运行。Docker容器是基于Docker镜像创建的,并且可以动态修改和更新容器中的应用程序和配置。容器可以启动、停止、暂停、恢复和删除。

可以将Docker镜像看作是应用程序的打包和分发方式,而Docker容器是应用程序的运行实例。在使用Docker时,通常首先构建一个Docker镜像,然后在Docker镜像的基础上创建多个Docker容器。这种分离的方式使得开发、测试、部署和运维过程更加高效、可靠和可重复。

输入一个网址,在浏览器的完整过程,越详细越好

  • 解析URL(Uniform Resource Locator,统一资源定位符)。 URL是指定网络资源的地址。URL由多个部分组成,例如协议(例如http或https)、主机名(例如www.example.com)、端口号、路径和查询字符串。浏览器会解析URL以确定要访问的主机名和路径。

  • 建立TCP连接。浏览器会使用HTTP(HyperText Transfer Protocol,超文本传输协议)或HTTPS(HTTP Secure,HTTPS是一种加密的HTTP)协议与Web服务器建立TCP连接。如果使用的是HTTPS,则还需要进行SSL/TLS握手以建立安全连接。

  • 发送HTTP请求。一旦TCP连接建立,浏览器会向Web服务器发送HTTP请求。请求中包括HTTP方法(例如GET或POST)、资源路径、HTTP版本、请求标头和消息正文(对于某些请求,例如POST请求)。

  • 接收HTTP响应。Web服务器将处理HTTP请求并生成HTTP响应。响应包括HTTP状态码、响应标头和响应正文。常见的HTTP状态码包括200 OK(请求成功)、404 Not Found(资源未找到)和500 Internal Server Error(服务器内部错误)。

  • 处理响应。一旦浏览器接收到HTTP响应,它会解析响应并执行以下操作:

    • 如果响应状态码为200,则解析响应正文并显示网页内容。

    • 如果响应状态码为3xx,则浏览器将遵循响应中指定的重定向URL以获取重定向后的资源。

    • 如果响应状态码为4xx或5xx,则浏览器将显示适当的错误页面。

  • 渲染页面。浏览器会将HTML、CSS和JavaScript代码解析为可视化页面,并在屏幕上呈现出来。页面可能包括文本、图像、视频和其他媒体元素。

  • 关闭TCP连接。一旦页面渲染完毕,浏览器会关闭TCP连接。

什么是 MVC?

模型、视图、控制器:解耦数据

  • M(Model)模型:负责业务对象和数据库的交互(ORM)

  • V(View)视图:负责与用户的交互展示

  • C(Control)控制器:接收请求参数调用模型和视图完成请求

ORM

ORM(Object Relational Mapping),对象关系映射,用于实现业务对象与数据表中的字段映射。比较出名的软件有:Sqlalchemy、Django ORM、Peewee

Web 框架对比 Django、flask、Fastapi、tornado

  • Django:高度集成的 Web 框架,适合开发复杂的 Web 应用程序,提供了大量的自带模块和插件,如:ORM、模板引擎、表单处理、认证等,非常适合快速搭建全功能的 Web 应用程序。但是自由度控制较少,有一定的学习曲线。

  • Flask:是一个轻量级的 Web 框架,比 Django 更为灵活,适合快速搭建小型的 Web 应用程序。提供了基本功能,如:路由、请求响应、模板引擎等,可通过插件来拓展功能。具有更高的自由度,但需要更多的手动配置和开发

  • FastAPI:FastAPI 是一个新兴的 Web 框架,以性能高和易用性强著称。FastAPI 基于 Python 3.7+ 的类型注解和异步编程模型,具有自动生成 API 文档、自动验证输入和输出数据等优秀特性。FastAPI 在处理高并发请求和异步 IO 方面表现出色,是构建高性能 Web 应用的不二之选。

  • Tornado:Tornado 是一个异步 Web 框架,特别适合处理大量的并发请求和实时流数据。Tornado 提供了基于协程的异步编程模型,其核心特性是非阻塞 IO 和事件驱动,比较适合构建长连接的 Web 应用程序,如聊天应用、实时推送等。

综上所述,选择哪个 Web 框架应该根据具体的应用场景和需求而定。如果需要开发高度集成、复杂的 Web 应用程序,可以选择 Django;如果需要开发轻量级、灵活的 Web 应用程序,可以选择 Flask;如果需要开发高性能的 Web 应用程序,可以选择 FastAPI 或 Tornado。

什么是 wsgi

WSGI(Web Server Gateway Interface)是 Python Web 应用程序和 Web 服务器之间的标准接口,它定义了 Web 服务器如何与 Python 应用程序进行通信。WSGI 规范主要包括两部分:服务器和应用程序之间的环境和通信协议。WSGI 的主要作用是为 Python Web 应用程序和 Web 服务器提供了一个标准的接口,让开发者可以使用不同的 Web 服务器来部署和运行他们的应用程序,同时也提高了 Web 应用程序的可移植性。

2 Django 框架

Django 中间件的使用场景是什么

是在请求和响应过程中位于视图函数前后的一系列可重用的组件,可用于拦截请求和响应,进行一些处理或修改,并将请求传递给下一个中间件或视图函数,应用场景:

  1. 认证和授权:验证是否登录或是否有权限访问特定页面

  2. 日志记录:记录请求和响应详细信息,包括请求时间、响应时间,请求方法、路径、响应状态码等,以便于调试和监控

  3. 缓存:提高网站性能和响应速度

  4. 异常处理:捕获视图函数中的异常,如发送邮件通知管理员等

Django 请求生命周期?

  • wsgi: 获取解析 HTTP 请求,并转发给 Web 框架

  • 中间件:对请求进行校验或在请求对象中添加其他相关数据,如:csrf、request、session

  • 路由匹配:根据请求 URL 去匹配不同的视图函数

  • 视图函数:在视图函数中进行业务逻辑的出来,涉及到:orm、templates => 渲染

  • 中间件:对响应的数据进行处理

  • wsgi:将响应的内容发送给浏览器

Django 内置组件?

  • Admin:对 model 中对应的数据表进行增删改查提供的组件

  • model:负责操作数据库

  • form 组件:生成 HTML 片段,对数据有效性进行校验

  • ModelForm:用于数据库操作,也可以用于用户请求的验证

列举 Django 中间件的 5 个方法,及应用场景?

  • process_request:请求进来时,权限验证

  • process_view:路由匹配之后,能够得到视图函数

  • process_exception:异常时执行

  • process_template_response:模板渲染时执行

  • process_response:请求有响应时执行

以上方法的返回值可以是 None,或者是一个HttpResponse对象,如果是 None,则继续按照django定义的规则向后继续执行,如果是 HttpResponse 对象,则直接将改对象返回给用户。

Django 的 request 对象是在什么时候创建的?

class WSGIHandler(base.BaseHandler):
    request = self.request_class(environ)

请求到 WSGIHandler 类的时候,执行 __cell__ 方法,将 environ 封装成 request

如何给 CBV 添加装饰器?

# 引入 method_decorator 模块
​
# 1. 直接给类加装饰器,所以请求方法(get、post 等)
@method_decorator(test, name='dispatch')
class LoginView(View):
    pass
​
# 2. 单独给请求的函数添加装饰器
@method_decorator
def post(self, request, *args, **kwargs):pass

Django 如何实现 csrf

只对 post 请求进行 csrf 防御,第一次请求时,会在服务端随机产生一个 token,把这个 token 放到 cookie 中,然后每次 post 请求都会携带这个 token,这样就能避免 csrf 攻击了。

Django 中如何实现单元测试?

使用 untest 模块,coverage 生成测试覆盖度报告。

简述 MVCMTV

  • MVCModel View Controller):模型-视图-控制器,是一种 Web 架构模式。特点:把业务逻辑、模型数据、用户界面分离开来,让开发者将数据与表现解耦

    • Model:模型,数据库层面

    • View:视图,系统中选择显示什么和如何显示的部分

    • Controller:系统中根据用户输入并视需要访问模型,以决定使用哪个视图的那部分

  • MTVModel Templates View):模型-模板-视图

    • Model:数据存取层,处理与数据所以事务,操作数据模型,如何读取数据等

    • Templates:表现层,将模型中的数据通过页面的形式展示给用户

    • View:业务逻辑层,包含存取模型以及调取恰当模板的相关逻辑,如:从模板中获取用户输入,写入模型中;从模型中读取数据放到模板中显示灯。

简述什么是FBV和CBV?

FBV和CBV本质是一样的,基于函数的视图叫做FBV,基于类的视图叫做CBV,使用 CBV 的优点:

  • 提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)

  • 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

Django本身提供了runserver,为什么不能用来部署?(runserver与uWSGI的区别)

  • runserver方法是调试 Django 时经常用到的运行方式,它使用Django自带的 WSGI Server 运行,主要在测试和开发中使用,并且 runserver 开启的方式也是单进程 。

  • uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http 等协议。注意uwsgi是一种通信协议,而uWSGI是实现uwsgi协议和WSGI协议的 Web 服务器。uWSGI具有超快的性能、低内存占用和多app管理等优点,并且搭配着Nginx就是一个生产环境了,能够将用户访问请求与应用 app 隔离开,实现真正的部署 。相比来讲,支持的并发量更高,方便管理多进程,发挥多核的优势,提升性能。

Django如何实现websocket?

Django-channels 模块

Django 是 MVC 还是 MTV 模式

Django采用了类似于MVC的设计模式,但是由于模板层的引入,所以Django更常用的被称作MTV,即Model-Template-View。其中:

  • Model:负责业务对象和数据库的关系映射(ORM)。

  • Template:负责如何把页面展示给用户(html)。

  • View:负责业务逻辑,并在适当时候调用Model和Template。

3. Flask 框架

Flask 上下文

在 Flask 中,有两种上下文:应用上下文和请求上下文。应用上下文包含了应用的全局状态,而请求上下文则包含了关于当前请求的信息

1、应用上下文:

在 Flask 中,应用上下文对象用于存储应用的全局状态,例如配置、插件、请求钩子等。应用上下文在应用启动时创建,并在应用关闭时销毁。在同一个线程中,应用上下文是共享的,可以使用 current_app 全局变量来访问应用上下文对象。

2、请求上下文:

在 Flask 中,请求上下文对象用于存储关于当前请求的信息,例如请求头、请求方法、URL 等。请求上下文对象在每个请求开始时创建,并在请求结束时销毁。在同一个线程中,请求上下文是独立的,可以使用 request 全局变量来访问请求上下文对象。

应用上下文和请求上下文可以使用 Flask 的 app_context()request_context() 函数进行手动创建,也可以使用 Flask 提供的 app 和 request 全局变量来隐式访问上下文对象。在使用 Flask 的扩展时,通常会隐式地使用上下文对象,因此开发者不需要手动创建。

下面是一个使用 Flask 上下文的简单示例:

from flask import Flask, request, current_app
​
app = Flask(__name__)
​
@app.route('/')
def hello_world():
    # 访问应用上下文对象
    print(current_app.name)
​
    # 访问请求上下文对象
    print(request.method)
    print(request.url)
    print(request.headers)
​
    return 'Hello, World!'

Flask 中请求钩子的理解和应用?

Flask 中的请求钩子是一种机制,用于在请求的不同阶段执行特定的操作。在 Flask 中,请求钩子主要有两种类型:before_request 和 after_request。

before_request 钩子会在每个请求处理之前被调用,可以用来执行一些全局操作,比如验证用户的登录状态、设置一些全局变量等。

  • 在 before_request 钩子中,可以通过返回 None 或一个 Response 对象来控制请求的继续处理或提前结束。如果返回 None,则请求会继续向下执行,而如果返回一个 Response 对象,则会提前结束请求处理,并返回该 Response 对象。

  • after_request 钩子会在每个请求处理结束之后被调用,可以用来执行一些请求结束后的全局操作,比如关闭数据库连接、设置一些响应头等。在 after_request 钩子中,可以修改响应对象并返回它,也可以返回原始的响应对象或一个新的 Response 对象。

下面是一个简单的例子,展示了如何使用 before_request 钩子来验证用户的登录状态:

from flask import Flask, request, abort
​
app = Flask(__name__)
​
@app.before_request
def check_login():
    if request.path != '/login' and not request.args.get('token'):
        abort(401, 'Unauthorized')
​
@app.route('/login')
def login():
    token = generate_token() # 生成登录 token
    return {'token': token}
​
@app.route('/data')
def get_data():
    # 获取数据
    return {'data': data}
​
if __name__ == '__main__':
    app.run()

上面的每个请求都会先经过 check_login() 函数验证是否登录,你也可以给不用验证的请求加白名单。

对 Flask 蓝图(Blueprint)的理解?

Flask 蓝图(Blueprint)是一种组织 Flask 应用的方式,它可以将应用拆分为一系列小的应用组件,从而使应用更加模块化和易于管理。蓝图可以包含一组相关的路由、模板、静态文件、错误处理等应用组件,并可以被注册到 Flask 应用中。在一个 Flask 应用中可以同时注册多个蓝图,它们之间相互独立,可以共同组成一个完整的应用。

Flask 蓝图的主要作用有以下几点:

  • 模块化应用:通过将应用拆分为多个蓝图,可以将不同功能的代码分开组织,从而提高应用的可读性和可维护性。

  • 组合多个应用:多个蓝图可以在一个 Flask 应用中并存,从而形成一个完整的应用,这样可以更灵活地组合多个应用。

  • 分离功能:蓝图可以让你将不同功能的代码分离开来,这样可以更好地重用代码、测试代码和独立部署不同功能的应用。

  • 分离权限:蓝图可以用来隔离不同权限的用户,从而更好地控制用户访问不同的功能。

使用 Flask 蓝图的基本步骤如下:

  • 创建一个蓝图对象:使用 Flask 的 Blueprint 类创建一个蓝图对象,可以指定蓝图的名称、导入名称、静态文件夹、模板文件夹等属性。

  • 注册路由和视图函数:在蓝图对象上使用装饰器注册路由和视图函数,与 Flask 应用中的路由和视图函数注册方式相同。

  • 注册蓝图:在 Flask 应用对象上使用 register_blueprint() 方法注册蓝图对象,可以指定蓝图对象的 URL 前缀、子域名等属性。

下面是一个简单的 Flask 蓝图的例子:

from flask import Blueprint
​
bp = Blueprint('auth', __name__, url_prefix='/auth')
​
@bp.route('/login')
def login():
    return 'Login page'
​
@bp.route('/logout')
def logout():
    return 'Logout page'

Flask 常用第三方组件

  • Flask-WTF:表单处理组件,提供了 CSRF 保护、表单验证等功能;

  • Flask-Login:用户认证组件,提供了登录、注销等功能;

  • Flask-Mail:邮件发送组件,可以方便地集成到应用中发送邮件;

  • Flask-RESTful:RESTful API 开发组件,提供了路由、参数解析、错误处理等功能;

  • Flask-SQLAlchemy:数据库 ORM 组件,支持多种关系型数据库,提供了简单易用的查询接口;

  • Flask-Caching:缓存组件,支持多种缓存类型,提供了简单的接口;

  • Flask-Admin:后台管理组件,提供了 CRUD 操作、搜索、过滤等功能;

  • Flask-Uploads:文件上传组件,支持多种存储方式,提供了上传验证、文件处理等功能;

  • Flask-Migrate:数据库迁移组件,可以方便地管理数据库结构的变更。

Web 安全

sql 注入

通过特殊的输入参数传入 web 应用,导致后端执行了恶意的 sql 语句

  • 通常由于程序员未对输入进行过滤,直接动态拼接 sql 产生

  • 可以使用开源工具 sqlmapsqlninja 检测

如何防范?

  • 永远不要相信用户的输入

  • 对输入参数做好检查(类型和范围),过滤和转义字符

  • 不要拼接 sql,使用占位符或者 ORM 可以大大降低 sql 注入的风险

  • 数据层:做好权限管理配置,不要明文存储存储信息

# sql 语句拼接(不推荐)
sql = "select * from users where name='"+ name +"' + "and password=md5('"+password+"')""
​
# SQL 语句注入,'---' 将后面的 SQL语句注释掉,从而到达不需要输入密码就能取出数据的目的
rose '--'
​
# 使用占位符
sql = "select * from users where name=%s and password=md5(%s)"

xss 跨站脚本攻击

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

  • 用户浏览的页面被恶意植入 JS 语句,其他用户访问同一个页面时,JS文件被执行,从而到达攻击用户的目的。

  • 主要分为两类:反射型(非持久型:放 url 中,发给用户,诱惑用户点击),存储型(持久型)

  • 危害:盗取用户 cookie,获取敏感信息

如何防范?

过滤用户输入的特殊字符,如:

你可能感兴趣的:(python,前端,开发语言)