Как принудительно использовать SSL для некоторых URL моего приложения Django?

Я хочу быть уверенным, что для некоторых URL моего сайта SSL будет использоваться. Я уже много видел ответа на SO.

принудительно перенаправить на SSL для всех страниц, кроме одного

Поэтому я думаю, что буду использовать mod_rewrite.

Мой вопрос в том, как настроить Виртуальный хост для запуска моего Django Application над HTTP и более HTTPS без проблем. Я использую WSGI.

Является ли проблема просто дублировать конфигурацию более *:443 и более *:80? Что делать, чтобы иметь лучшую конфигурацию?

Ответ 1

Если по WSGI вы фактически имеете в виду Apache/mod_wsgi, то, хотя установленные WSGI-приложения обычно запускаются в своих собственных суб-интерпретаторах, разделение 80/443 является особым случаем, и хотя в разных VirtualHost до тех пор, пока точка монтирования для WSGIScriptAlias, и ServerName совпадают, они будут объединены.

<VirtualHost *:80>
ServerName www.example.com

WSGIScriptAlias / /some/path/django.wsgi.
</VirtualHost>

<VirtualHost *:443>
ServerName www.example.com

WSGIScriptAlias / /some/path/django.wsgi.
</VirtualHost>

Это также произойдет и для режима демона, но в режиме демона вам нужно определить только одну группу процессов демона в первом определении VirtualHost, а затем просто обратиться к ней с помощью WSGIProcessGroup.

<VirtualHost *:80>
ServerName www.example.com

WSGIDaemonProcess mydjangosite ...
WSGIProcessGroup mydjangosite

WSGIScriptAlias / /some/path/django.wsgi.
</VirtualHost>

<VirtualHost *:444>
ServerName www.example.com

WSGIProcessGroup mydjangosite

WSGIScriptAlias / /some/path/django.wsgi.
</VirtualHost>

WSGIProcessGroup может достигать только этого VirtualHost для того же самого имени сервера.

Django предоставляет метод is_secure() для определения, когда запрос поступает через HTTPS, который происходит из переменной WSGI с запросом, называемым "wsgi.url_scheme", который устанавливается mod_wsgi.

Итак, у вас будет один файл и файл настроек Django WSGI script. Вам просто нужно дублировать установку приложения как decsribed в конфигурации Apache/mod_wsgi.

Ответ 2

Помимо использования mod_rewrite, вы также можете использовать Django для управления переадресацией SSL.

Здесь представлена ​​модифицированная версия промежуточного программного обеспечения из Satchmo Project. Мне нравится этот метод лучше, чем mod_rewrite, так как его легче управлять.

Чтобы использовать его, перейдите 'SSL': True в ваш url conf:


    urlpatterns = patterns('some_site.some_app.views',
        (r'^test/secure/$','test_secure',{'SSL':True}),
    )

Здесь код промежуточного кода:


    from django.conf import settings
    from django.http import HttpResponseRedirect, get_host

    SSL = 'SSL'

    def request_is_secure(request):
        if request.is_secure():
            return True

        # Handle forwarded SSL (used at Webfaction)
        if 'HTTP_X_FORWARDED_SSL' in request.META:
            return request.META['HTTP_X_FORWARDED_SSL'] == 'on'

        if 'HTTP_X_SSL_REQUEST' in request.META:
            return request.META['HTTP_X_SSL_REQUEST'] == '1'

        return False

    class SSLRedirect:
        def process_request(self, request):
            if request_is_secure(request):
                request.IS_SECURE=True
            return None

        def process_view(self, request, view_func, view_args, view_kwargs):          
            if SSL in view_kwargs:
                secure = view_kwargs[SSL]
                del view_kwargs[SSL]
            else:
                secure = False

            if settings.DEBUG:
                return None

            if getattr(settings, "TESTMODE", False):
                return None

            if not secure == request_is_secure(request):
                return self._redirect(request, secure)

        def _redirect(self, request, secure):
            if settings.DEBUG and request.method == 'POST':
                raise RuntimeError(
                """Django can't perform a SSL redirect while maintaining POST data.
                    Please structure your views so that redirects only occur during GETs.""")

            protocol = secure and "https" or "http"

            newurl = "%s://%s%s" % (protocol,get_host(request),request.get_full_path())

            return HttpResponseRedirect(newurl)

Ответ 3

Вот декоратор вида, который можно применить к представлениям, которые должны иметь HTTPS.

from functools import wraps
from django.conf import settings
from django.http import HttpResponseRedirect


def require_https(view):
    """A view decorator that redirects to HTTPS if this view is requested
    over HTTP. Allows HTTP when DEBUG is on and during unit tests.

    """

    @wraps(view)
    def view_or_redirect(request, *args, **kwargs):
        if not request.is_secure():
            # Just load the view on a devserver or in the testing environment.
            if settings.DEBUG or request.META['SERVER_NAME'] == "testserver":
                return view(request, *args, **kwargs)

            else:
                # Redirect to HTTPS.
                request_url = request.build_absolute_uri(request.get_full_path())
                secure_url = request_url.replace('http://', 'https://')
                return HttpResponseRedirect(secure_url)

        else:
            # It HTTPS, so load the view.
            return view(request, *args, **kwargs)

    return view_or_redirect

Ответ 4

Мы использовали простейшее промежуточное программное обеспечение для проверки URL-адресов в отношении списка базовых URL-адресов, которые должны быть в режиме HTTPS, а все остальные - в режиме HTTP. Большой оговоркой здесь является то, что любые данные POST могут быть потеряны, если вы не проявите особой осторожности (в нашем случае это не имело значения). Мы делали это на страницах присоединения, которые требовали номера кредитных карт и тому подобное, поэтому, как только они были в этом конвейере, мы вынудили их перейти на HTTPS.