API 的应用 URL 路径 /api/v1/getcode 将生成包含字母数字代码和时间戳的 JSON 响应。
首先, @app.route 修饰器告知 Flask get_code 函数处理 对 /api/v1/getcode URL 的请求。
@app.route('/api/v1/getcode', methods=['GET'])
def get_code():
接下来,应用调用第三方 API,该 API 的 URL 位于其中 number_url,提供从标头中的密钥保管库中检索的访问密钥。
headers = {
'Content-Type': 'application/json',
'x-functions-key': access_key
}
r = requests.get(url = number_url, headers = headers)
if (r.status_code != 200):
return "Could not get you a code.", r.status_code
示例第三方 API 部署到 Azure Functions 的无服务器环境。
x-functions-key标头中的属性是 Azure Functions 期望访问密钥出现在标头中的方式。 有关详细信息,请参阅 Azure Functions HTTP 触发器 - 授权密钥。 如果出于任何原因调用 API 失败,代码将返回错误消息和状态代码。
假设 API 调用成功并返回数值,应用随后会使用该数字和一些随机字符(使用自己的 random_char 函数)构造更复杂的代码。
data = r.json()
chars1 = random_char(3)
chars2 = random_char(3)
code_value = f"{chars1}-{data['value']}-{chars2}"
code = { "code": code_value, "timestamp" : str(datetime.utcnow()) }
此处 code 的变量包含应用 API 的完整 JSON 响应,其中包括代码值和时间戳。 一个示例响应是 {"code":"ojE-161-pTv","timestamp":"2020-04-15 16:54:48.816549"}。
但是,在返回该响应之前,它会使用队列客户端 send_message 的方法在存储队列中写入消息:
queue_client.send_message(code)
return jsonify(code)
处理队列消息
可以通过 Azure 门户、Azure CLI 命令 az storage message get 或 Azure 存储资源管理器查看和管理队列中存储的消息。 示例存储库包含一个脚本(test.cmd 和 test.sh),用于从应用终结点请求代码,然后检查消息队列。 还有一个脚本,用于使用 az storage message clear 命令清除队列。
通常,类似于此示例中的应用会有另一个进程,该进程异步从队列中拉取消息以供进一步处理。 如前所述,此 API 终结点生成的响应可能在应用中的其他地方使用双因素用户身份验证。 在这种情况下,应用应在某个时间段后使代码失效,例如 10 分钟。 执行此任务的一种简单方法是维护有效的双因素身份验证代码表,该代码由其用户登录过程使用。 然后,应用程序将有一个简单的队列监视流程,逻辑如下(用伪代码表示):
pull a message from the queue and retrieve the code.
if (code is already in the table):
remove the code from the table, thereby invalidating it
else:
add the code to the table, making it valid
call queue_client.send_message(code, visibility_timeout=600)
此伪代码采用 send_message 方法的可选 visibility_timeout 参数,该参数指定消息在队列中可见之前的秒数。 由于默认超时为零,API 终结点最初写入的消息会立即对队列监视进程可见。 因此,该过程会立即将其存储在有效的代码表中。 进程在超时后再次对同一消息进行排队,以便在 10 分钟后再次收到代码,此时会将其从表中删除。
在 Azure Functions 中实现主应用 API 终结点
本文前面显示的代码使用 Flask Web 框架创建其 API 终结点。 由于 Flask 需要使用 Web 服务器运行,因此此类代码必须部署到 Azure 应用服务或虚拟机。
备用部署选项是 Azure Functions 的无服务器环境。 在这种情况下,所有启动代码和 API 终结点代码都将包含在绑定到 HTTP 触发器的同一函数中。 与应用服务一样,可以使用 函数应用程序设置 为代码创建环境变量。
一个更容易实现的实现是使用队列存储进行身份验证。 无需使用队列的 URL 和凭据对象获取 QueueClient 对象,而是为函数创建 队列存储绑定 。 绑定处理后台的所有身份验证。 使用此类绑定时,函数会提供一个现成的客户端对象作为参数。 有关详细信息和示例代码,请参阅 将 Azure Functions 连接到 Azure 队列存储。
后续步骤
通过本教程,你了解了应用如何使用托管标识与其他 Azure 服务进行身份验证,以及应用如何使用 Azure Key Vault 存储第三方 API 的任何其他必要机密。
此处通过 Azure Key Vault 和 Azure 存储演示的相同模式适用于所有其他 Azure 服务。 关键步骤是,在 Azure 门户上或通过 Azure CLI 为该服务页面中的应用分配正确的角色。 (请参阅 如何分配 Azure 角色)。 请务必检查服务文档,以查看是否需要配置任何其他访问策略。
请记住,需要为用于本地开发的任何服务主体分配相同的角色和访问策略。
简言之,完成本演练后,可以将知识应用于任何其他 Azure 服务和任意数量的其他外部服务。
本教程中未涉及的一个主题是对 用户进行身份验证。 若要探索 Web 应用的此区域,请从 身份验证开始,并在 Azure 应用服务中授权用户端到端。