如何强制使用SSL为我的Django应用程序的某些URL?

Nat*_*tim 11 apache django mod-rewrite ssl wsgi

我想确保对于我网站的某些网址,我会使用SSL.我已经看到了很多答案.

强制重定向到除一个以外的所有页面的SSL

所以我想我会用mod_rewrite.

我的问题更多的是关于如何配置虚拟主机以反复运行我的Django应用程序HTTPHTTPS不会出现问题.我在用WSGI.

一遍*:443又一遍地复制配置是一个问题*:80吗?我该怎么做才能拥有最佳配置?

Gra*_*ton 11

如果你通过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>
Run Code Online (Sandbox Code Playgroud)

对于守护进程模式也会发生这种情况,但是对于守护进程模式,您需要在第一个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>
Run Code Online (Sandbox Code Playgroud)

对于相同的ServerName,WSGIProcessGroup只能与VirtualHost类似.

Django提供了一个is_secure()方法,用于确定何时通过HTTPS发出请求,该请求来自WSGI变量,其请求名为'wsgi.url_scheme',由mod_wsgi设置.

因此,您将拥有一个Django WSGI脚本文件和设置文件.您只需要在Apache/mod_wsgi配置中复制应用程序挂载.


Chi*_*Tol 10

除了使用mod_rewrite之外,您还可以使用Django来控制SSL重定向.

这是Satchmo项目中间件的修改版本.我倾向于比mod_rewrite更喜欢这种方法,因为它更容易管理.

要使用它,请将"SSL":True传递到您的网址:


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

这是中间件代码:


    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)

Run Code Online (Sandbox Code Playgroud)