إشعار
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تسجيل الدخول أو تغيير الدلائل.
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تغيير الدلائل.
هام
اعتبارا من 1 مايو 2025، لن يكون Azure AD B2C متوفرا للشراء للعملاء الجدد. تعرف على المزيد في الأسئلة المتداولة.
في هذه المقالة، ستتعلم كيفية إضافة مصادقة Azure Active Directory B2C (Azure AD B2C) في تطبيق ويب Python الخاص بك. يمكنك تمكين المستخدمين من تسجيل الدخول وتسجيل الخروج وتحديث ملف التعريف وإعادة تعيين كلمة المرور باستخدام تدفقات مستخدم Azure AD B2C. تستخدم هذه المقالة مكتبة مصادقة Microsoft (MSAL) ل Python لتبسيط إضافة المصادقة إلى تطبيق ويب Python.
الهدف من هذه المقالة هو استبدال نموذج التطبيق الذي استخدمته في تكوين المصادقة في نموذج تطبيق ويب Python باستخدام Azure AD B2C مع تطبيق Python الخاص بك.
تستخدم هذه المقالة Python 3.9+وFlask 2.1 لإنشاء تطبيق ويب أساسي. تستخدم طرق عرض التطبيق قوالب Jinja2.
المتطلبات الأساسية
- أكمل الخطوات في تكوين المصادقة في نموذج تطبيق ويب Python باستخدام Azure AD B2C. يمكنك إنشاء تدفقات مستخدم Azure AD B2C وتسجيل تطبيق ويب في مدخل Microsoft Azure.
- تثبيت Python 3.9 أو أعلى
- Visual Studio Code أو محرر آخر للتعليمات البرمجية
- تثبيت ملحق Python ل Visual Studio Code
الخطوة 1: إنشاء مشروع Python
على نظام الملفات الخاص بك، قم بإنشاء مجلد مشروع لهذا البرنامج التعليمي، مثل
my-python-web-app.في المحطة الطرفية، قم بتغيير الدليل إلى مجلد تطبيق Python، مثل
cd my-python-web-app.قم بتشغيل الأمر التالي لإنشاء بيئة ظاهرية باسم وتنشيطها
.venvاستنادا إلى المترجم الحالي.- Linux
-
macOS - نوافذ
sudo apt-get install python3-venv # If needed python3 -m venv .venv source .venv/bin/activateتحديث النقطة في البيئة الظاهرية عن طريق تشغيل الأمر التالي في المحطة الطرفية:
python -m pip install --upgrade pipلتمكين ميزات تتبع أخطاء Flask، قم بتبديل Flask إلى بيئة التطوير إلى
developmentالوضع. لمزيد من المعلومات حول تصحيح أخطاء تطبيقات Flask، راجع وثائق Flask.- Linux
-
macOS - نوافذ
export FLASK_ENV=developmentافتح مجلد المشروع في VS Code عن طريق تشغيل
code .الأمر، أو عن طريق فتح VS Code وتحديد File>Open Folder.
الخطوة 2: تثبيت تبعيات التطبيق
ضمن المجلد الجذر لتطبيق الويب الخاص بك، قم بإنشاء requirements.txt الملف. يسرد ملف المتطلبات الحزم التي سيتم تثبيتها باستخدام تثبيت pip. أضف المحتوى التالي إلى ملف requirements.txt:
Flask>=2
werkzeug>=2
flask-session>=0.3.2,<0.5
requests>=2,<3
msal>=1.7,<2
في المحطة الطرفية، قم بتثبيت التبعيات عن طريق تشغيل الأوامر التالية:
- Linux
-
macOS - نوافذ
python -m pip install -r requirements.txt
الخطوة 3: إنشاء مكونات واجهة مستخدم التطبيق
Flask هو إطار عمل Python خفيف الوزن لتطبيقات الويب التي توفر أساسيات توجيه عنوان URL وعرض الصفحة. ويستخدم Jinja2 كمحرك قالب لعرض محتوى تطبيقك. لمزيد من المعلومات، راجع وثائق مصمم القالب. في هذا القسم، يمكنك إضافة القوالب المطلوبة التي توفر الوظائف الأساسية لتطبيق الويب الخاص بك.
الخطوة 3.1 إنشاء قالب أساسي
يحتوي قالب الصفحة الأساسية في Flask على جميع الأجزاء المشتركة لمجموعة من الصفحات، بما في ذلك مراجع ملفات CSS وملفات البرنامج النصي وما إلى ذلك. تحدد القوالب الأساسية أيضا علامة كتلة واحدة أو أكثر من المتوقع أن تتجاوزها القوالب الأخرى التي توسع القاعدة. يتم تحديد علامة الكتلة بواسطة {% block <name> %} و {% endblock %} في كل من القالب الأساسي والقالب الموسع.
في المجلد الجذر لتطبيق الويب الخاص بك، قم بإنشاء templates المجلد. في مجلد القوالب، أنشئ ملفا باسم base.html، ثم أضف المحتويات أدناه:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% block metadata %}{% endblock %}
<title>{% block title %}{% endblock %}</title>
<!-- Bootstrap CSS file reference -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('index')}}">Python Flask demo</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{{ url_for('index')}}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('graphcall')}}">Graph API</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container body-content">
<br />
{% block content %}
{% endblock %}
<hr />
<footer>
<p>Powered by MSAL Python {{ version }}</p>
</footer>
</div>
</body>
</html>
الخطوة 3.2 إنشاء قوالب تطبيق الويب
أضف القوالب التالية ضمن مجلد القوالب. توسع هذه القوالب القالب base.html :
index.html: الصفحة الرئيسية لتطبيق الويب. تستخدم القوالب المنطق التالي: إذا لم يقم المستخدم بتسجيل الدخول، فإنه يعرض زر تسجيل الدخول. إذا سجل المستخدم الدخول، فإنه يعرض مطالبات الرمز المميز للوصول، ويربط بتحرير ملف التعريف، ويستدعي واجهة برمجة تطبيقات Graph.
{% extends "base.html" %} {% block title %}Home{% endblock %} {% block content %} <h1>Microsoft Identity Python Web App</h1> {% if user %} <h2>Claims:</h2> <pre>{{ user |tojson(indent=4) }}</pre> {% if config.get("ENDPOINT") %} <li><a href='/graphcall'>Call Microsoft Graph API</a></li> {% endif %} {% if config.get("B2C_PROFILE_AUTHORITY") %} <li><a href='{{_build_auth_code_flow(authority=config["B2C_PROFILE_AUTHORITY"])["auth_uri"]}}'>Edit Profile</a></li> {% endif %} <li><a href="/logout">Logout</a></li> {% else %} <li><a href='{{ auth_url }}'>Sign In</a></li> {% endif %} {% endblock %}graph.html: يوضح كيفية استدعاء واجهة برمجة تطبيقات REST.
{% extends "base.html" %} {% block title %}Graph API{% endblock %} {% block content %} <a href="javascript:window.history.go(-1)">Back</a> <!-- Displayed on top of a potentially large JSON response, so it will remain visible --> <h1>Graph API Call Result</h1> <pre>{{ result |tojson(indent=4) }}</pre> <!-- Just a generic json viewer --> {% endblock %}auth_error.html: يعالج أخطاء المصادقة.
{% extends "base.html" %} {% block title%}Error{% endblock%} {% block metadata %} {% if config.get("B2C_RESET_PASSWORD_AUTHORITY") and "AADB2C90118" in result.get("error_description") %} <!-- See also https://learn.microsoft.com/azure/active-directory-b2c/active-directory-b2c-reference-policies#linking-user-flows --> <meta http-equiv="refresh" content='0;{{_build_auth_code_flow(authority=config["B2C_RESET_PASSWORD_AUTHORITY"])["auth_uri"]}}'> {% endif %} {% endblock %} {% block content %} <h2>Login Failure</h2> <dl> <dt>{{ result.get("error") }}</dt> <dd>{{ result.get("error_description") }}</dd> </dl> <a href="{{ url_for('index') }}">Homepage</a> {% endblock %}
الخطوة 4: تكوين تطبيق الويب الخاص بك
في المجلد الجذر لتطبيق الويب الخاص بك، أنشئ ملفا باسم app_config.py. يحتوي هذا الملف على معلومات حول موفر هوية Azure AD B2C. يستخدم تطبيق الويب هذه المعلومات لإنشاء علاقة ثقة مع Azure AD B2C، وتسجيل دخول المستخدمين والخروج، والحصول على الرموز المميزة، والتحقق من صحتها. أضف المحتويات التالية إلى الملف:
import os
b2c_tenant = "fabrikamb2c"
signupsignin_user_flow = "B2C_1_signupsignin1"
editprofile_user_flow = "B2C_1_profileediting1"
resetpassword_user_flow = "B2C_1_passwordreset1" # Note: Legacy setting.
authority_template = "https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{user_flow}"
CLIENT_ID = "Enter_the_Application_Id_here" # Application (client) ID of app registration
CLIENT_SECRET = "Enter_the_Client_Secret_Here" # Application secret.
AUTHORITY = authority_template.format(
tenant=b2c_tenant, user_flow=signupsignin_user_flow)
B2C_PROFILE_AUTHORITY = authority_template.format(
tenant=b2c_tenant, user_flow=editprofile_user_flow)
B2C_RESET_PASSWORD_AUTHORITY = authority_template.format(
tenant=b2c_tenant, user_flow=resetpassword_user_flow)
REDIRECT_PATH = "/getAToken"
# This is the API resource endpoint
ENDPOINT = '' # Application ID URI of app registration in Azure portal
# These are the scopes you've exposed in the web API app registration in the Azure portal
SCOPE = [] # Example with two exposed scopes: ["demo.read", "demo.write"]
SESSION_TYPE = "filesystem" # Specifies the token cache should be stored in server-side session
قم بتحديث التعليمات البرمجية أعلاه بإعدادات بيئة Azure AD B2C كما هو موضح في قسم تكوين نموذج تطبيق الويب في مقالة تكوين المصادقة في نموذج تطبيق ويب Python .
الخطوة 5: إضافة التعليمات البرمجية لتطبيق الويب
في هذا القسم، يمكنك إضافة وظائف عرض Flask وأساليب مصادقة مكتبة MSAL. ضمن المجلد الجذر لمشروعك، أضف ملفا باسم app.py مع التعليمات البرمجية التالية:
import uuid
import requests
from flask import Flask, render_template, session, request, redirect, url_for
from flask_session import Session # https://pythonhosted.org/Flask-Session
import msal
import app_config
app = Flask(__name__)
app.config.from_object(app_config)
Session(app)
# This section is needed for url_for("foo", _external=True) to automatically
# generate http scheme when this sample is running on localhost,
# and to generate https scheme when it is deployed behind reversed proxy.
# See also https://flask.palletsprojects.com/en/1.0.x/deploying/wsgi-standalone/#proxy-setups
from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
@app.route("/anonymous")
def anonymous():
return "anonymous page"
@app.route("/")
def index():
#if not session.get("user"):
# return redirect(url_for("login"))
if not session.get("user"):
session["flow"] = _build_auth_code_flow(scopes=app_config.SCOPE)
return render_template('index.html', auth_url=session["flow"]["auth_uri"], version=msal.__version__)
else:
return render_template('index.html', user=session["user"], version=msal.__version__)
@app.route("/login")
def login():
# Technically we could use empty list [] as scopes to do just sign in,
# here we choose to also collect end user consent upfront
session["flow"] = _build_auth_code_flow(scopes=app_config.SCOPE)
return render_template("login.html", auth_url=session["flow"]["auth_uri"], version=msal.__version__)
@app.route(app_config.REDIRECT_PATH) # Its absolute URL must match your app's redirect_uri set in AAD
def authorized():
try:
cache = _load_cache()
result = _build_msal_app(cache=cache).acquire_token_by_auth_code_flow(
session.get("flow", {}), request.args)
if "error" in result:
return render_template("auth_error.html", result=result)
session["user"] = result.get("id_token_claims")
_save_cache(cache)
except ValueError: # Usually caused by CSRF
pass # Simply ignore them
return redirect(url_for("index"))
@app.route("/logout")
def logout():
session.clear() # Wipe out user and its token cache from session
return redirect( # Also logout from your tenant's web session
app_config.AUTHORITY + "/oauth2/v2.0/logout" +
"?post_logout_redirect_uri=" + url_for("index", _external=True))
@app.route("/graphcall")
def graphcall():
token = _get_token_from_cache(app_config.SCOPE)
if not token:
return redirect(url_for("login"))
graph_data = requests.get( # Use token to call downstream service
app_config.ENDPOINT,
headers={'Authorization': 'Bearer ' + token['access_token']},
).json()
return render_template('graph.html', result=graph_data)
def _load_cache():
cache = msal.SerializableTokenCache()
if session.get("token_cache"):
cache.deserialize(session["token_cache"])
return cache
def _save_cache(cache):
if cache.has_state_changed:
session["token_cache"] = cache.serialize()
def _build_msal_app(cache=None, authority=None):
return msal.ConfidentialClientApplication(
app_config.CLIENT_ID, authority=authority or app_config.AUTHORITY,
client_credential=app_config.CLIENT_SECRET, token_cache=cache)
def _build_auth_code_flow(authority=None, scopes=None):
return _build_msal_app(authority=authority).initiate_auth_code_flow(
scopes or [],
redirect_uri=url_for("authorized", _external=True))
def _get_token_from_cache(scope=None):
cache = _load_cache() # This web app maintains one cache per session
cca = _build_msal_app(cache=cache)
accounts = cca.get_accounts()
if accounts: # So all account(s) belong to the current signed-in user
result = cca.acquire_token_silent(scope, account=accounts[0])
_save_cache(cache)
return result
app.jinja_env.globals.update(_build_auth_code_flow=_build_auth_code_flow) # Used in template
if __name__ == "__main__":
app.run()
الخطوة 6: تشغيل تطبيق الويب الخاص بك
في المحطة الطرفية، قم بتشغيل التطبيق عن طريق إدخال الأمر التالي، الذي يقوم بتشغيل خادم تطوير Flask. يبحث app.py خادم التطوير بشكل افتراضي. ثم افتح المتصفح وانتقل إلى عنوان URL لتطبيق الويب: http://localhost:5000.
- Linux
-
macOS - نوافذ
python -m flask run --host localhost --port 5000
[اختياري] تصحيح أخطاء تطبيقك
تمنحك ميزة تصحيح الأخطاء الفرصة لإيقاف برنامج قيد التشغيل مؤقتا على سطر معين من التعليمات البرمجية. عند إيقاف البرنامج مؤقتا، يمكنك فحص المتغيرات، وتشغيل التعليمات البرمجية في لوحة Debug Console، وبخلاف ذلك الاستفادة من الميزات الموضحة في تصحيح الأخطاء. لاستخدام مصحح أخطاء Visual Studio Code، تحقق من وثائق VS Code.
لتغيير اسم المضيف و/أو رقم المنفذ، استخدم args صفيف launch.json الملف. يوضح المثال التالي كيفية تكوين اسم المضيف إلى localhost ورقم المنفذ إلى 5001. ملاحظة، إذا قمت بتغيير اسم المضيف أو رقم المنفذ، يجب تحديث عنوان URI لإعادة التوجيه أو التطبيق الخاص بك. لمزيد من المعلومات، راجع خطوة تسجيل تطبيق ويب .
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Flask",
"type": "python",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "app.py",
"FLASK_ENV": "development"
},
"args": [
"run",
"--host=localhost",
"--port=5001"
],
"jinja": true,
"justMyCode": true
}
]
}
المحتوى ذو الصلة
- تعرف على كيفية تخصيص وتحسين تجربة مصادقة Azure AD B2C لتطبيق الويب الخاص بك