HttpResponseRedirect を使って http[s], ftp 以外へリダイレクトさせようとすると下記のように SuspiciousOperation 例外が発生する。
SuspiciousOperation: Unsafe redirect to URL with protocol 'com.example.app.sample0'
以下のようなコードを追加すればこの例外を回避できる。allowed_schemes に例外を発生させたくないリダイレクト先を追加すればよい。
try:
from django.http.response import HttpResponseRedirectBase
HttpResponseRedirectBase.allowed_schemes += ['com.example.app.sample0', ]
except ImportError:
pass
import に関して、古いバージョンでは django.http 以下が reponse, request に分かれていなかった。なので Django のバージョンが古いとき(1.4系以前くらい、細かいバージョンは失念)は import は以下のようなコード。
from django.http import HttpResponseRedirectBase
通常ブラウザで閲覧する Web ページの範囲であれば http[s], ftp 以外のリダイレクト先に飛ばしたいことはまずない。例えばスマホアプリをターゲットとしているときに '[アプリパッケージ名]://' にリダイレクトしたい(例:OAuthで認証用URLからアプリに制御を戻すとき)とか、そういったケースで使える。
補足
リダイレクト時のこの例外は Django 1.4 系で導入された。
HttpResponseRedirectBase の実際のコードは下記のようになっており allowed_schemes にリダイレクト先を追記すればいいことが容易に分かる。セキュリティ対策のために導入されたコードなので、上のサンプルのように極力リダイレクト先を限定するような記述にするのがよいと考えられる。
response.py
class HttpResponseRedirectBase(HttpResponse):
allowed_schemes = ['http', 'https', 'ftp']
def __init__(self, redirect_to, *args, **kwargs):
parsed = urlparse(redirect_to)
if parsed.scheme and parsed.scheme not in self.allowed_schemes:
raise SuspiciousOperation("Unsafe redirect to URL with protocol '%s'" % parsed.scheme)
super(HttpResponseRedirectBase, self).__init__(*args, **kwargs)
self['Location'] = iri_to_uri(redirect_to)
url = property(lambda self: self['Location'])