雖然咱們已經實現了重定向會上一個頁面的功能,可是安全問題不容忽視,鑑於referer和next容易被串篡改的特性,咱們須要對這些值進行驗證,不然會造成開放重定向漏洞
以URL中的next參數爲例,next變量以字符串的形式寫在url裏,所以任何人均可以發給某個用戶一個包含next變量指向任何站點的鏈接,那麼就會誤導用戶進入釣魚網站。
咱們能夠驗證next變量指向的url地址是否屬於咱們的應用內,不然不容許重定向。
確保URL安全的關鍵是判斷URL是否屬於程序內部,能夠經過判斷url的host、協議等信息是否和程序內部的url一致,若是一致則認識是可信的url
代碼中is_safe_url()方法接受目標URL做爲參數,經過request.host_url獲取程序內部的主機URL,而後使用urljoin()函數將目標URL轉爲絕對URL。接着,分別使用urlparse模塊提供的urlparse()解析兩個url,最後對目標url的url模式和主機地址進行驗證,確保只屬於程序內部的url纔會被返回。
在執行重定向會上一個頁面的redirect_back()函數中,使用is_safe_url()驗證next和referer的值
from urlparse import urlparse, urljoin #python3須要從urllib.parse導入
from flask import request
@app.route('/bar')
def bar():
print "request.full_path:",request.full_path
return '<h1>Bar page</h1><a href="%s">Do something and redirect </a>' % url_for('do_something', next = request.full_path)
@app.route('/do_something_and_redirect')
def do_something():
return redirect_back()
def is_safe_url(target):
print "request.host_url:",request.host_url
ref_url = urlparse(request.host_url)
print "ref_url:",ref_url
print "target:",target
test_url = urlparse(urljoin(request.host_url, target))
print "test_url:",test_url
print "ref_url.netloc:",ref_url.netloc
print "test_url.netloc:",test_url.netloc
print "test_url.scheme:",test_url.scheme
return test_url.scheme in ('http', 'https') and ref_url.netloc ==test_url.netloc
def redirect_back(default = 'hello',**kwargs):
for target in request.args.get('next'),request.referrer:
if target:
if is_safe_url(target):
return redirect(target)
return redirect(url_for(default,**kwargs))
if __name__ == '__main__':
app.run(debug = True)
結果:python
控制檯輸出:flask
request.host_url: http://127.0.0.1:5000/安全
ref_url: ParseResult(scheme=u'http', netloc=u'127.0.0.1:5000', path=u'/', params='', query='', fragment='')app
target: /bar?函數
test_url: ParseResult(scheme=u'http', netloc=u'127.0.0.1:5000', path=u'/bar', params='', query='', fragment='')網站
ref_url.netloc: 127.0.0.1:5000url
test_url.netloc: 127.0.0.1:5000.net
test_url.scheme: httpdebug
request.full_path: /bar?3d
頁面: