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

如何在带Azure授权的Flask应用中未登录时跳转至登录页?

解决方案

要实现未登录用户访问受保护页面时自动跳转Azure AD登录,登录后返回原页面,需要调整认证逻辑,添加授权码流的处理步骤,具体修改如下:

1. 补充必要配置

需添加Session密钥、Azure AD客户端密钥、回调URI等配置项,这些信息可从Azure AD应用注册页面获取:

  • SECRET_KEY:用于加密Session数据,生产环境请使用随机且安全的密钥
  • AZURE_OAUTH_CLIENT_SECRET:Azure AD应用注册中生成的客户端密码
  • AZURE_OAUTH_REDIRECT_URI:需在Azure AD应用注册的“身份验证”页面提前配置,需与代码中完全一致

2. 自定义登录验证装饰器

替换原有的@auth()装饰器,实现未认证时自动重定向到登录页,并保存用户原本访问的路径:

3. 添加登录回调路由

处理Azure AD返回的授权码,交换并验证Token,完成登录后跳转回用户最初访问的受保护页面:

完整修改代码

from flask import Flask, redirect, url_for, session, request
from flask_azure_oauth import FlaskAzureOauth

app = Flask(__name__)

# 基础配置
app.config['SECRET_KEY'] = 'your-strong-secret-key-here'  # 生产环境请使用安全的随机密钥
app.config['AZURE_OAUTH_TENANCY'] = 'your-tenant-id'
app.config['AZURE_OAUTH_APPLICATION_ID'] = 'your-app-id'
app.config['AZURE_OAUTH_CLIENT_SECRET'] = 'your-client-secret'  # Azure AD应用注册生成的客户端密钥
app.config['AZURE_OAUTH_REDIRECT_URI'] = 'http://127.0.0.1:5000/callback'  # 需与Azure AD中配置的重定向URI一致
app.config['AZURE_OAUTH_SCOPES'] = ['openid', 'profile']  # 登录所需的基础权限范围

auth = FlaskAzureOauth()
auth.init_app(app)

def login_required(scopes=None):
    def decorator(f):
        def wrapped(*args, **kwargs):
            # 检查Session中是否存在有效Token
            token = session.get('access_token')
            if token:
                try:
                    # 验证Token及权限范围
                    auth.validate_token(token, scopes)
                    return f(*args, **kwargs)
                except Exception:
                    # Token无效时清除Session,重新触发登录流程
                    session.clear()
            
            # 保存当前访问路径,登录后跳转回该页面
            session['next_url'] = request.url
            # 生成Azure AD授权URL并跳转
            auth_url = auth.get_authorization_url(scopes=scopes)
            return redirect(auth_url)
        return wrapped
    return decorator

@app.route('/unprotected')
def unprotected():
    return 'hello world'

@app.route('/protected')
@login_required()
def protected():
    return 'hello authenticated entity'

@app.route('/protected-with-single-scope')
@login_required('required-scope')
def protected_with_scope():
    return 'hello authenticated and authorised entity'

@app.route('/protected-with-multiple-scopes')
@login_required(['required-scope1', 'required-scope2'])
def protected_with_multiple_scopes():
    return 'hello authenticated and authorised entity'

@app.route('/callback')
def callback():
    # 获取Azure AD返回的授权码
    code = request.args.get('code')
    if not code:
        return 'Authorization code missing', 400
    
    try:
        # 用授权码交换Access Token
        token_response = auth.get_token_from_code(code)
        access_token = token_response.get('access_token')
        
        # 验证Token有效性
        auth.validate_token(access_token)
        
        # 将有效Token存入Session
        session['access_token'] = access_token
        
        # 跳转回用户最初访问的页面,默认跳转到/protected
        next_url = session.pop('next_url', '/protected')
        return redirect(next_url)
    except Exception as e:
        return f'Login failed: {str(e)}', 401

if __name__ == '__main__':
    app.run(debug=True)

关键说明

  • Session作用:用于临时存储用户的访问路径和有效Token,确保登录后能返回原页面
  • Azure AD配置校验:务必保证代码中的重定向URI、客户端密钥与Azure AD应用注册中的配置完全匹配,否则会导致登录失败
  • 装饰器逻辑:login_required会自动处理未认证场景,无需手动判断401状态码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 19:52:54