Flask实现谷歌登录后如何将用户重定向回原始访问URL
Flask 谷歌登录后重定向回原始页面实现方案
通用实现逻辑
核心思路是在检测到用户未登录时,把当前访问的原始路径存入用户session,登录流程完成后从session取出该路径完成跳转,避免用URL参数直接传递可能出现的篡改风险。
基于flask-dance的实现步骤
- 首先给需要登录校验的路由加自定义装饰器,未登录时记录原始路径
from flask import session, redirect, url_for, request from functools import wraps def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): if not google.authorized: # 此处google为你初始化的flask-dance谷歌provider实例 # 把当前请求的完整路径存入session session["next_url"] = request.full_path return redirect(url_for("google.login")) return f(*args, **kwargs) return decorated_function
- 给目标路由加登录校验装饰器
@app.route("/results") @login_required def results(): # 你的业务逻辑 return render_template("results.html")
- 处理登录成功后的回调逻辑,读取session里的next_url跳转
如果是自定义回调路由,直接在登录态校验完成后加跳转逻辑即可:
@app.route("/login/callback") def google_callback(): # 此处保留你原有获取用户信息、保存登录态的逻辑 # 登录态校验通过后跳转 next_url = session.pop("next_url", url_for("index")) # 无next_url时默认跳首页 return redirect(next_url)
如果使用flask-dance自带的回调,可以用before_sender信号监听登录成功事件后处理跳转:
from flask_dance.contrib.google import google from flask_dance.consumer import oauth_authorized @oauth_authorized.connect_via(google) def google_logged_in(blueprint, token): # 你的登录态保存逻辑 next_url = session.pop("next_url", url_for("index")) return redirect(next_url)
基于authlib Flask客户端的实现步骤
- 登录校验装饰器的实现和上述flask-dance的逻辑完全一致
- 触发谷歌登录跳转时,把next_url存入session
@app.route("/login/google") def google_login(): next_url = request.args.get("next", request.referrer or url_for("index")) session["next_url"] = next_url # 生成授权跳转地址,authlib会自动处理state参数 redirect_uri = url_for("google_authorize", _external=True) return oauth.google.authorize_redirect(redirect_uri)
- 回调处读取session的next_url跳转
@app.route("/login/google/authorize") def google_authorize(): token = oauth.google.authorize_access_token() user_info = oauth.google.parse_id_token(token) # 此处保留你自己的用户信息保存、登录态写入session逻辑 next_url = session.pop("next_url", url_for("index")) return redirect(next_url)
安全注意事项
要校验next_url的域名和当前站点域名一致,避免开放重定向漏洞,可以加以下校验逻辑:
from urllib.parse import urlparse, urljoin def is_safe_url(target): ref_url = urlparse(request.host_url) test_url = urlparse(urljoin(request.host_url, target)) return test_url.scheme in ("http", "https") and ref_url.netloc == test_url.netloc # 跳转前调用校验 if not is_safe_url(next_url): next_url = url_for("index")
内容的提问来源于stack exchange,提问作者akshansh
相关产品推荐
相关产品推荐

