Flask之安全地重定向回来
表单处理的常见模式是自动重定向回用户。 通常有两种方法:检查下一个URL参数或查看HTTP引用者。
不幸的是,您还必须确保用户不会被重定向到恶意攻击者的页面,而只是重定向到同一主机。 如果您使用的是Flask-WTF,
那么有一种更好的方法:使用Flask-WTF重定向。确保重定向目标将指向同一服务器的函数位于:
Part1
from urllib.parse import urlparse,urljoin # python3
# python2 from urlparse import urlparse, urljoin
from flask import request, url_for
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
part2
使用它的一种简单方法是编写一个get_redirect_target函数,该函数查看各种提示以查找重定向目标:
def get_redirect_target():
for target in request.values.get('next'), request.referrer:
if not target:
continue
if is_safe_url(target):
return target
part3
由于我们不想重定向到同一页面,我们必须确保实际的后向重定向略有不同(仅使用提交的数据,而不是引用者)。 我们也可以在那里有一个后备:
def redirect_back(endpoint, **values):
target = request.form['next']
if not target or not is_safe_url(target):
target = url_for(endpoint, **values)
return redirect(target)
part4
它将首先尝试使用next和referrer,然后回退到给定的端点。 然后,您可以在视图中使用它:
@app.route('/login', methods=['GET', 'POST'])
def login():
next = get_redirect_target()
if request.method == 'POST':
# login code here
return redirect_back('index')
return render_template('index.html', next=next)
part5
重要的是,如果所有提示都失败(在这种情况下是索引页面),我们就有一个重定向目标。
在模板中,您必须确保中继重定向目标:
<form action="" method=post>
<dl>
<dt>Username:
<dd><input type=text name=username>
<dt>Password:
<dd><input type=password name=password>
</dl>
<p>
<input type=submit value=Login>
<input type=hidden value="{{ next or '' }}" name=next>
</form>
或者就在这里使None成为一个空字符串。
Armin Ronacher的这个片段可以随意用于任何你喜欢的内容。 考虑它是公共领域。
Great works are not done by strength, but by persistence!