如何在带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
相关产品推荐
相关产品推荐

