准备用于身份验证的 Python Flask Web 应用
本教程是一个系列教程的第 2 部分,演示如何生成 Python Flask Web 应用,并使用 Microsoft 标识平台添加登录支持。 在本系列教程的第 1 部分中,你在 Microsoft Entra ID 租户中注册和配置了应用程序。
在本教程中,你将了解:
- 创建新的 Python Flask Web 应用项目
- 安装应用依赖项
- 添加应用程序的 UI 组件
- 将 Flask Web 应用配置为使用 Microsoft Entra ID 进行身份验证
先决条件
- 完成教程:在 Microsoft 标识平台注册 Python Web 应用中的步骤。
- Visual Studio Code 或任何其他 IDE。
- 本地安装的 Python 3.9 或更高版本。
创建新的 Python Web 应用项目
若要完成本教程的其余部分,需要创建 Python Flask Web 应用项目。 如果希望使用已完成的代码示例进行学习,请从 GitHub 下载 Python Flask Web 应用示例。
若要从头开始构建 Python Flask Web 应用,请执行以下步骤:
- 创建一个文件夹来托管应用程序,并将其命名为 flask-web-app。
- 导航到项目目录并创建三个名为 app.py、app.config.py 和 requirements.txt 的文件。
- 在项目的根文件夹中创建 .env 文件。
- 在项目根目录中创建名为 templates 的文件夹。 Flask 查找此子目录中的呈现模板。
创建文件后,项目的文件和目录应类似于以下结构:
python-webapp/
├── templates/
│ ├── display.html
│ ├── index.html
│ ├── login.html
├── .env.sample
├── app.py
├── app.config.py
│── requirements.txt
安装应用依赖项
构建的守护程序应用使用 identity
包,即适用于 Python 的 Microsoft 身份验证库 (MSAL) 周围的包装器。 还需安装 Flask、Flask 会话、请求以及应用需要的所有其他依赖项。 使用这些依赖项更新“requirements.txt”。
Flask>=2.2
Flask-Session>=0.3.2,<0.6
werkzeug>=2
requests>=2,<3
identity>=0.5.1,<0.6
python-dotenv<0.22
添加应用程序 UI 组件
在本部分中,将为应用中定义的每个路由创建 HTML 模板,包括登录、注销、API 调用和错误模板。 按照以下步骤为每个页面创建模板:
登录模板
在 templates 文件夹中,创建一个名为 login.html 的 HTML 文件,并添加以下内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Microsoft Identity Python Web App: Login</title>
</head>
<body>
<h1>Microsoft Identity Python Web App</h1>
{% if user_code %}
<ol>
<li>To sign in, type <b>{{ user_code }}</b> into
<a href='{{ auth_uri }}' target=_blank>{{ auth_uri }}</a>
to authenticate.
</li>
<li>And then <a href="{{ url_for('auth_response') }}">proceed</a>.</li>
</ol>
{% else %}
<ul><li><a href='{{ auth_uri }}'>Sign In</a></li></ul>
{% endif %}
<hr>
<footer style="text-align: right">Microsoft identity platform Web App Sample {{ version }}</footer>
</body>
</html>
此模板表示用户可以登录到应用程序的登录页。
索引模板
在 templates 文件夹中,创建一个名为 index.html 的 HTML 文件,并添加以下内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Microsoft Identity Python Web App: Index</title>
</head>
<body>
<h1>Microsoft Identity Python Web App</h1>
<h2>Welcome {{ user.get("name") }}!</h2>
<ul>
{% if config.get("ENDPOINT") %}
<li><a href='/call_downstream_api'>Call a downstream API</a></li>
{% endif %}
<li><a href="/logout">Logout</a></li>
</ul>
<hr>
<footer style="text-align: right">Microsoft identity platform Web App Sample {{ version }}</footer>
</body>
</html>
索引模板充当 Web 应用的主页,在用户访问应用的根 URL 时呈现。
“显示”页面
此模板用于显示下游 API 调用的结果。 将以下代码片段添加到 display.html。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Microsoft Identity Python Web App: API</title>
</head>
<body>
<a href="javascript:window.history.go(-1)">Back</a> <!-- Displayed on top of a potentially large JSON response, so it will remain visible -->
<h1>Result of the downstream API Call</h1>
<pre>{{ result |tojson(indent=4) }}</pre> <!-- Just a generic json viewer -->
</body>
</html>
错误模板
身份验证错误模板
在 templates 文件夹中,创建一个名为 auth_error.html 的 HTML 文件,该文件显示可能出现的任何错误消息。 将以下代码添加到 auth_error.html。
<!DOCTYPE html>*
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Microsoft Identity Python Web App: Error</title>
</head>
<body>
<h2>Login Failure</h2>
<dl>
{#
Flask automatically escapes these unsafe input, so we do not have to.
See also https://flask.palletsprojects.com/en/2.0.x/templating/#jinja-setup
#}
<dt>{{ result.get("error") }}</dt>
<dd>{{ result.get("error_description") }}</dd>
</dl>
<hr>
<a href="{{ url_for('index') }}">Homepage</a>
</body>
</html>
配置错误模板
在 templates 文件夹中,创建一个名为 config_error.html 的 HTML 文件,该文件显示所需配置缺失时的消息。 将以下代码添加到 config_error.html。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Microsoft Identity Python Web App: Error</title>
</head>
<body>
<h2>Config Missing</h2>
<p>
Almost there. Did you forget to set up
<a target=_blank
href="https://learn.microsoft.com/azure/active-directory/develop/web-app-quickstart?pivots=devlang-python#step-5-configure-the-sample-app">
necessary environment variables</a> for your deployment?
</p>
<hr>
<a href="{{ url_for('index') }}">Homepage</a>
</body>
</html>
创建 配置文件
在代码编辑器中,打开保存配置参数的 app_config.py,并添加以下代码:
import os
AUTHORITY= os.getenv("AUTHORITY")
# Application (client) ID of app registration
CLIENT_ID = os.getenv("CLIENT_ID")
# Application's generated client secret: never check this into source control!
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
REDIRECT_PATH = "/getAToken" # Used for forming an absolute URL to your redirect URI.
ENDPOINT = 'https://graph.microsoft.com/v1.0/me'
SCOPE = ["User.Read"]
# Tells the Flask-session extension to store sessions in the filesystem
SESSION_TYPE = "filesystem"
创建 .env 文件以存储配置设置。
在此示例中,你将使用 .env 文件来存储和管理不应嵌入到代码中的应用程序配置设置、环境变量和凭据。 打开在项目目录的根目录中创建的 .env 文件,然后添加以下值。
# The following variables are required for the app to run.
CLIENT_ID=<client id>
CLIENT_SECRET=<client secret>
AUTHORITY=<Enter_your_authority_url>
在 .env.sample 文件中替换以下占位符:
-
- 将
CLIENT_ID
替换为应用注册概述页上提供的“应用程序(客户端) ID”。 - 将
CLIENT_SECRET
替换为在“证书和机密”中创建的客户端机密 AUTHORITY
将 替换为https://login.microsoftonline.com/<TENANT_GUID>
。 应用注册概述页上提供了“目录(租户) ID”。
- 将
下一步
了解如何向 Python Flask Web 应用添加登录支持(本系列教程的下一部分):