2024 Exam
Q1
a. 在计算机科学中,协议是什么意思?
在计算机科学中,特别是在网络通信领域,协议是指计算机和网络设备之间用于通信和解释数据流的一套共同语言或规则。网络通信之所以成为可能,正是因为计算机“讲”同一种语言,并且知道如何解释传输的二进制数据(如0和1序列)。这些预定义的协议告诉计算机如何解释这些数据流。互联网的核心是 TCP/IP 模型,这是一组协议,无论何种类型的计算机系统连接到互联网,只要使用 TCP/IP,就可以与其他类型的计算机交换数据。
b. 给出万维网中使用的 2 个协议示例并解释其用途。
万维网构建在互联网之上。以下是万维网中使用的两个协议示例及其用途:
- HTTP (超文本传输协议):HTTP 是万维网中客户端(例如网络浏览器)与服务器之间约定使用的协议。用户通过浏览器向服务器请求网页。浏览器作为客户端,找到正确的服务器并通过 HTTP 协议发送请求。服务器根据请求,从其本地文件系统(或动态生成)检索网页文件,并通过 HTTP 将文件传输回浏览器。HTTP 是万维网应用层常用的协议。
- TCP (传输控制协议):TCP 是 TCP/IP 模型的一部分,属于传输层协议。其主要用途是保证数据的可靠传输。在不可靠的物理网络层之上(例如电线、Wi-Fi 或卫星链路),TCP 将数据流分成多个数据包,并通过网络单独发送。它负责检测和修复传输过程中丢失或损坏的数据包,使用校验和、签名和确认等机制,确保整个消息最终以正确的顺序完整地到达目的地。对于需要保证传输的通信,使用 TCP/IP 而不是 UDP(用户数据报协议)。
c. 协议不限于计算机科学。举一个开车时使用的协议示例。
关于开车时使用的协议的信息不在您提供的来源或我们的对话历史中。
然而,举一个来自一般知识的开车时使用的协议示例是:交通信号灯。在红灯亮起时停车就是一种协议。所有驾驶员都理解并遵守这一规则(协议),以确保交通安全和有序流动。
Q2
The five parts of the HTML philosophy are: • Interoperability • Graceful error recovery • Backwards compatibility • Prioritising users • Separation of concerns.
a. 解释“互操作性”(Interoperability)的含义。 “互操作性”意味着HTML应该能够在各种不同的浏览器上正确地呈现。
b. 解释“优雅的错误恢复”(Graceful error recovery)的含义并提供一个例子。 “优雅的错误恢复”意味着即使存在一些小错误,也不应该阻止页面正常渲染。 根据来源,为了实现优雅的错误恢复,网页浏览器渲染器非常宽松。浏览器会忽略一些内容,例如:
- 未识别的标签。
- 换行符。
- 制表符和多个空格。
- 即使是关键文档标签如
<html>
,<head>
, 甚至<body>
也没有必要存在。 - 即使没有匹配的开始和结束标签(尽管强烈建议匹配,因为这是常见的错误来源)。
- 标签仅仅是对浏览器的建议,即使被浏览器识别,也可能被忽略。 一个例子是,如果您在HTML文档中使用了浏览器无法识别的自定义标签,或者忘记了关闭某些标签,浏览器通常不会因此停止渲染整个页面,而是尝试忽略这些错误并继续显示页面的其余部分。
c. 结合上述HTML哲学,解释为什么<b>
标签的定义发生了变化,以及为什么<b>
标签没有被移除并替换成例如<important>
标签。 <b>
标签最初在原始HTML规范中用于“标记应使用粗体字体显示的文本” [部分在问题中提供]。这主要是关于文本的外观或样式。 在HTML4中,其定义被更改为“引起读者的注意,其内容并未被赋予特别重要性” [部分在问题中提供]。这更多地是关于文本的语义或意义。
这种定义的变化与HTML5哲学中的“关注点分离”原则直接相关。该原则强调“描述信息的类型,而不是它如何显示”。原始的<b>
定义侧重于显示(粗体),而新的定义侧重于语义(引起注意)。这种改变使得HTML更加专注于描述内容的结构和类型,而将外观和样式的工作留给CSS(层叠样式表)。
关于为什么<b>
标签没有被完全移除并替换成如<important>
这样的新标签,这与HTML5哲学中的“向后兼容”原则有关。该原则指出“新功能不应该破坏现有网络”。<b>
标签在旧的网页中被广泛使用。如果将其完全移除,将导致大量现有网页在渲染时出现问题,从而破坏了网络的稳定性和用户体验。
此外,“优先考虑用户”的哲学(用户>网页设计师>浏览器实现者>理论家)也可能在决定保留<b>
标签(尽管重新定义了其语义)中发挥了作用。移除一个广泛使用的标签会给网页设计师带来负担,需要更新现有内容;同时,如果旧内容因此无法正常显示,也会影响用户。
因此,更改<b>
标签的定义是出于将外观与语义分离的哲学考量,使其更符合描述内容类型的目标。而没有移除它,则是为了保持向后兼容,避免破坏现有网络,并优先考虑用户和网页设计师的体验。
Q3
<body>
<div id="q1">
<!-- ... other elements ... -->
<div>
<!-- ... other elements ... -->
<p id="warning"> (If you're sure you got it right!) </p>
<button id="saveButton" class="myButton" autofocus> Save </button>
<button id="loadButton" class="myButton" autofocus> Load </button>
</div>
</div>
</body>
a. 我们将找到定位 元素的六种不同的 CSS 选择器表达式,并将其背景颜色设置为红色。
- element selector
- attribute selector
Save 以及 Load 按钮都具备 autofocus
属性都会被匹配
- ID selector
- Two element selectors and a direct descendent selector.
- A class selector, an attribute selector and a sibling selector.
- Three ID selectors, a direct sibling selector, a descendant selector
可以是空格也可以是 >
b. Explain two advantages of making your CSS selectors as specific as possible.
确保样式被应用并覆盖不太具体的规则:使用具体性高的选择器(例如 ID 选择器 [#id]
的特异性高于类选择器 [.class]
的特异性,类选择器高于元素选择器 [element]
的特异性)可以提高您规则的优先级。这意味着即使同一元素受到来自用户代理样式表(浏览器默认样式)用户样式表或其他作者样式表中特异性较低的规则的影响,您的具体规则也会因为更高的特异性而被优先应用。这对于在复杂的网页结构或使用多个样式表时,确保某个元素获得您指定的精确样式至关重要。
防止样式被意外覆盖:如果您使用了特异性较低的选择器,那么在其他地方(例如,在样式表的后面或不同的样式文件中)添加的、特异性更高的规则可能会意外地覆盖您的样式。通过使您的选择器尽可能具体,您就增加了该规则的特异性权重,降低了其被后续添加的、但特异性不如它的规则意外覆盖的风险。这有助于提高样式定义的稳定性,减少不必要的调试工作。虽然特异性过高也可能导致难以覆盖的问题(可能需要使用更具体的选择器或 !important
来覆盖),但在需要保证样式应用时,“尽可能具体”确实有助于防止意外覆盖。
Q4
a. Explain the difference between “formal parameters” and “actual parameters” in JavaScript, including what values they take and when and how they may be accessed.
function example(firstName, lastName) {
// firstName 和 lastName 是形式参数
console.log(firstName, lastName);
}
example('John', 'Doe'); // 'John' 和 'Doe' 是实际参数
b. 详情直接看 l5_ex
Q5
a. 解释 Git 和 GitHub 之间的区别 (4 分)
Git 是一种 分布式版本控制系统 (Distributed Version Control System)。其核心目的是帮助开发者 跟踪和管理代码变更历史,并 支持团队协作。Git 记录代码的每一次修改,并能将代码恢复到之前的某个稳定状态。Git 项目的历史记录被构造成一个非线性的图结构,图中的每个节点代表一组代码更改,称为提交 (commit)。它提供了处理不同开发者对同一代码部分修改之间冲突的机制。Git 由 Linus Torvalds 于 2005 年开发,是目前世界上使用最广泛的版本控制系统。
而 GitHub 是一个 托管 Git 仓库的服务平台。它的目的是为 Git 仓库提供 在线存储。通过 GitHub,团队成员可以将其 Git 仓库放在一个中心位置,并通过从 GitHub 仓库拉取 (pull) 和向其推送 (push) 代码来进行 协作开发。除了代码托管,GitHub 还提供一系列工具来支持敏捷项目管理,如 问题跟踪 (Issues) 和 代码审查 (Code Review),这些功能通过拉取请求 (Pull requests) 实现。因此,区别在于:
- Git 是一个软件工具 (版本控制系统) ,用于管理代码的变更历史和协作。
- GitHub 是一个在线平台 (服务) ,用于托管 Git 仓库,并提供额外的协作和项目管理功能。
您可以把 Git 想象成您本地电脑上的一个强大的文件管理工具,而 GitHub 则是互联网上的一个社交和存储平台,让您可以存储您的文件(代码)并与他人共享和协作。
b. 在本地 Git 仓库中,您刚刚为 Flask 服务器添加了一个新的路由,该路由返回当前用户最喜欢的泡泡茶吸管类型。git status
命令返回以下输出:
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
modified: app/models.py
modified: app/routes.py
给出一个简单的 Git 命令序列,使得您所做的更改存储在 main
分支上 - 包括在本地仓库和名为 origin
的远程仓库中。 (3 分)
根据 git status
的输出,您对 app/models.py
和 app/routes.py
进行了修改,但这些修改尚未被暂存 (staged) 以进行提交。要将这些更改存储在本地 main
分支并推送到远程 origin
仓库,您需要执行以下命令序列:
- 暂存更改:使用
git add
命令将修改的文件添加到暂存区。
(选择其中一种即可)
- 提交更改:使用
git commit
命令将暂存区的更改提交到本地仓库的当前分支 (main
)。提交时需要提供一个提交信息 (commit message) 来描述本次更改的目的和内容。
(提交信息应清晰说明本次提交做了什么)
- 推送更改:使用
git push
命令将本地main
分支的提交推送到名为origin
的远程仓库的main
分支。
所以,一个完整的命令序列是:
git add app/models.py app/routes.py
git commit -m "Add new route for favourite bubble tea straw type"
git push origin main
或者:
c. 选择 part b 中的一个命令,解释它可能不会成功的原因。您无需描述如何修复问题。(1 分)
我选择命令 git push origin main
。
这个命令可能不会成功的问题是,自您上次从远程仓库 origin
拉取代码以来,远程仓库的 main
分支可能已经被其他人更新了。换句话说,远程仓库 origin/main
包含了您本地仓库 main
分支中没有的提交。当您尝试推送您的本地提交时,Git 会检测到远程仓库有新的提交历史,并且您的提交不是基于最新的远程提交进行的。在这种情况下,推送会被拒绝,您需要先拉取远程的最新更改,解决可能出现的合并冲突(如果您的更改与远程的更改修改了同一文件的相同部分),然后才能再次尝试推送。
Q6
Server-Side Rendering, SSR
Pros
- 有利于 搜索引擎优化 (SEO),因为搜索引擎爬虫可以直接抓取完整的页面内容
- 首次内容加载速度通常更快 (First Contentful Paint)
Cons
- 每次页面更新通常需要重新生成并发送整个页面,这在开发和带宽方面重量级且昂贵。
- 每次更新都需要发送大量数据,可能导致延迟。
- 服务器负责大部分渲染工作,服务器负载较高
Single Page Application, SPA
服务器初始发送一个基本的 HTML 骨架以及 CSS 和 JavaScript 文件。页面的大部分内容不是在服务器上生成的。客户端的 JavaScript 代码接收到这些文件后执行,并利用从服务器异步获取的数据(通常通过 AJAX 请求,格式如 JSON)来动态构建或修改页面结构。页面更新通过发送少量数据并仅修改 DOM 的特定部分来完成
SPA 整个网站通常由一个 HTML 页面提供是客户端渲染的一种极致应用
Pros:
- 减轻服务器负载,因为客户端承担了大部分渲染和逻辑工作
- 理论上可以提供更流畅、响应更快的用户体验,因为页面更新无需完整的页面重新加载
- 可以使用同一个后端 API 为 Web 应用和原生移动应用提供数据
Cons:
- 初始加载时间可能较长,因为需要传输和执行大量的 JavaScript 代码。
- 搜索引擎优化 (SEO) 是个问题,传统爬虫可能无法抓取动态生成的内容。
- 浏览器的前进和后退按钮、以及页面刷新可能会出现问题,行为可能不稳定。
Q7
跨站请求伪造 (CSRF) 攻击如何工作
跨站请求伪造攻击利用的是用户可能已经在一个服务器上进行了身份验证的事实。攻击者会诱骗用户(例如,通过电子邮件中的一个链接)向他们已经登录的网站发出一个非预期的请求(例如,向银行网站发起一笔转账请求)。
在这种情况下,用户的浏览器会自动发送与该网站域名关联的 cookies。服务器接收到请求和 cookie 后,会检查 cookie 并认为该请求来自合法用户,然后执行相应的操作。即使这个请求是由用户无意中触发的(例如,点击了攻击者提供的恶意链接),服务器也会因为它带有有效的身份验证 cookie 而将其视为合法请求并执行。
如何在 Flask 中防御 CSRF 攻击
防御 CSRF 攻击的核心方法是在服务器渲染表单时,生成一个秘密令牌(secret token)并将其包含在表单中。这个令牌是使用 Flask 配置中的 secret key 生成的随机数。攻击者由于不知道服务器的 secret key,无法伪造 这个令牌。
当用户提交表单时(通常是通过一个 POST 请求),提交的数据中也会包含这个秘密令牌。服务器在处理请求时,会检查并验证提交的令牌是否有效,例如在 Flask-WTF 表单的 validate_on_submit
方法中进行验证。这样,服务器只响应通过官方表单生成的请求,而忽略那些没有有效令牌或令牌不匹配的请求。
在 Flask 中,Flask-WTF(它使用了 WTForms 库)为 CSRF 保护提供了极大的便利。您需要在 Flask 应用配置中设置一个 SECRET_KEY。在模板中渲染表单时,需要包含一个隐藏字段来输出 CSRF 令牌。WTForms 会自动生成这个令牌。例如,在 Jinja 模板中,您可以使用 {{ form.csrf_token }}
或 {{ form.hidden_tag() }}
来包含必要的隐藏字段,其中包含了 CSRF 令牌。当表单提交时,Flask-WTF 会自动验证此令牌。
此安全敏感的应用程序通常会非常快速地使签名的 cookie 超时(例如,大约 5 分钟),这也可以作为一种辅助防御措施。
Q8
API 将基于 RESTful 架构风格设计,使用 HTTP 协议进行通信,并通过 URL 识别资源。数据交换格式将主要采用 JSON。
API 的基础 URL 假定为 www.bubbleT.com/api/v1
。
核心 API 端点:
- 获取所有商店列表 [根据项目需求] - HTTP 方法:
GET
- URL 路径:/api/v1/stores
- 目的: 允许客户端获取所有商店的简要信息,以便用户选择 [根据项目需求]。 - 响应: JSON 格式的商店列表(例如[{"id": 1, "name": "主店"}, ...]
)[根据项目需求, 15, 56]。 - 获取特定商店的口味列表 [根据项目需求] - HTTP 方法:
GET
- URL 路径:/api/v1/stores/{store_id}/flavors
- 目的: 获取指定商店提供的所有口味及其详细信息 [根据项目需求]。 - 路径参数:{store_id}
- 商店的唯一标识符。 - 查询参数(可选):sort_by
(可选值:name
,price
),order
(可选值:asc
,desc
) 用于排序 [根据项目需求, 56]。 - 响应: JSON 格式的口味列表,包含名称、价格、图片 URL 和点赞数 [根据项目需求, 15, 31, 56]。 - 点赞特定口味 [根据项目需求] - HTTP 方法:
POST
- URL 路径:/api/v1/flavors/{flavor_id}/likes
- 目的: 增加指定口味的总点赞数 [根据项目需求]。 - 路径参数:{flavor_id}
- 口味的唯一标识符。 - 请求体: 通常为空或包含非敏感信息。基于项目要求“不跟踪任何关于我们客户的信息”,服务器不识别或存储点赞客户信息 [根据项目需求]。 - 处理: 每次成功调用此端点,服务器简单地将该口味的点赞总数加 1 [根据项目需求]。 - 响应: 可能返回更新后的点赞总数或口味信息 [根据项目需求]。
核心假设:
- API 使用 JSON 进行数据交换。
- API 使用标准 HTTP 状态码(如 200 OK, 404 Not Found)表示结果。
- 点赞功能不关联具体的客户身份信息 [根据项目需求]。
- 口味图片通过 URL 提供,而不是直接嵌入响应数据中 [31, 根据项目需求]。
- 商店、口味和点赞数等数据存储在服务器端的数据库中 [25, 根据项目需求]。
- 同一客户可以多次点赞同一口味,每次点赞都会计入总数 [根据项目需求]。