You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flask移动端应用集成Microsoft Entra External ID并保留现有流程?

将Microsoft Entra External ID集成到Flask移动端应用的方案

不用完全重写现有代码,可以通过渐进式集成保留你现有核心业务流程,以下是具体实现思路和步骤:

一、现有流程的保留策略

  • 身份验证层替换,业务逻辑保留:把原有的自定义账号密码认证替换为Entra External ID的OAuth2/OpenID Connect认证,但管理员授权标志(0/1)、私有ID的业务逻辑完全可以复用SQL Server中的现有表结构。
  • 用户关联逻辑:用户通过Entra验证身份后,后端用Entra返回的唯一标识(比如用户邮箱、oid)去查询你的SQL Server用户表,匹配到对应记录后,读取授权状态和私有ID,继续走原有业务流程。
  • 兼容过渡(可选):如果需要,可以同时保留原自定义认证和Entra认证,逐步迁移用户,待验证稳定后再下线原认证。

二、Flask集成的核心实现步骤

1. 安装依赖

使用Microsoft官方的MSAL库处理Entra认证:

pip install msal flask-sqlalchemy

2. 配置Entra应用参数

在Flask配置中添加Entra相关信息:

app.config.update(
    CLIENT_ID="你的Entra应用客户端ID",
    TENANT_ID="你的租户ID(多租户场景用common)",
    AUTHORITY=f"https://login.microsoftonline.com/{app.config['TENANT_ID']}",
    REDIRECT_PATH="/getAToken",  # 回调路由,需提前在Entra应用中配置
    SCOPE=["User.Read"],  # 按需调整所需权限
    SQLALCHEMY_DATABASE_URI="mssql+pyodbc://用户名:密码@SQLServer地址/数据库名?driver=ODBC+Driver+17+for+SQL+Server"
)

3. 实现认证路由

from flask import Flask, redirect, request, session, jsonify
import msal
from models import User  # 假设你的SQLAlchemy用户模型对应现有表结构

app = Flask(__name__)
app.secret_key = "你的Flask密钥"

# 初始化MSAL客户端
msal_client = msal.ConfidentialClientApplication(
    app.config["CLIENT_ID"],
    authority=app.config["AUTHORITY"],
    client_credential="你的Entra应用客户端密码"
)

@app.route("/login")
def login():
    # 生成Entra登录跳转URL
    auth_url = msal_client.get_authorization_request_url(
        app.config["SCOPE"],
        redirect_uri=request.host_url + app.config["REDIRECT_PATH"]
    )
    return redirect(auth_url)

@app.route(app.config["REDIRECT_PATH"])
def authorized():
    # 处理Entra认证回调,获取令牌
    code = request.args.get("code")
    result = msal_client.acquire_token_by_authorization_code(
        code,
        scopes=app.config["SCOPE"],
        redirect_uri=request.host_url + app.config["REDIRECT_PATH"]
    )

    if "error" in result:
        return jsonify({"error": result["error"]}), 401

    # 从ID令牌中提取用户唯一标识(示例用邮箱)
    user_email = result["id_token_claims"]["email"]
    # 查询现有SQL Server用户表
    user = User.query.filter_by(email=user_email).first()

    if not user:
        # 可选逻辑:首次登录自动创建用户记录,等待管理员授权
        user = User(email=user_email, is_authorized=0, private_id=None)
        db.session.add(user)
        db.session.commit()
        return jsonify({"message": "请等待管理员授权"}), 403

    # 检查管理员授权状态
    if not user.is_authorized:
        return jsonify({"message": "未授权用户"}), 403

    # 将私有ID存入会话,供后续业务接口使用
    session["private_id"] = user.private_id
    return jsonify({"message": "登录成功", "private_id": user.private_id})

# 原有业务接口示例,复用私有ID逻辑
@app.route("/get-utility-info")
def get_utility_info():
    private_id = session.get("private_id")
    if not private_id:
        return jsonify({"error": "未认证"}), 401
    # 原有业务逻辑:用private_id查询实用信息
    # ...
    return jsonify({"data": "实用信息内容"})

4. 后端接口的令牌验证

对于需要保护的接口,要验证Entra的ID令牌有效性:

def validate_id_token(id_token):
    # 验证令牌签名、受众、有效期等信息
    result = msal_client.validate_id_token(id_token, audience=app.config["CLIENT_ID"])
    return result is not None

三、关键注意事项

  • 用户同步:现有用户需提前将邮箱(或其他唯一标识)与Entra用户信息匹配,避免登录时找不到对应记录。
  • 权限最小化:Entra应用仅申请必要权限(如User.Read),避免过度授权。
  • 会话适配移动端:移动端可通过Bearer令牌传递认证信息,替代Flask默认的Cookie会话,适配APP场景。

内容的提问来源于stack exchange,提问作者user23370582

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 11:26:22