我想确保对于我网站的某些 URL,将使用 SSL。我已经在 SO 上看到了很多答案。
所以我想我会用mod_rewrite
.
我的问题更多是关于如何配置虚拟主机以一遍又一遍地运行我的Django 应用程序而不会出现问题。我正在使用.HTTP
HTTPS
WSGI
*:443
一遍又一遍地复制配置是否有问题*:80
?我应该怎么做才能获得最佳配置?
我想确保对于我网站的某些 URL,将使用 SSL。我已经在 SO 上看到了很多答案。
所以我想我会用mod_rewrite
.
我的问题更多是关于如何配置虚拟主机以一遍又一遍地运行我的Django 应用程序而不会出现问题。我正在使用.HTTP
HTTPS
WSGI
*:443
一遍又一遍地复制配置是否有问题*:80
?我应该怎么做才能获得最佳配置?
如果通过 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 只能通过相同的 ServerName 访问该 VirtualHost。
Django 提供了一个 is_secure() 方法来确定何时通过 HTTPS 发出请求,该方法源自 WSGI 变量,请求名为“wsgi.url_scheme”,由 mod_wsgi 设置。
因此,您将拥有一个 Django WSGI 脚本文件和设置文件。您只需要按照 Apache/mod_wsgi 配置中的说明复制应用程序安装。
除了使用 mod_rewrite,您还可以使用 Django 来控制 SSL 重定向。
这是来自Satchmo 项目的中间件的修改版本。我倾向于比 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)
这是一个视图装饰器,您可以将其应用于应该具有 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's HTTPS, so load the view.
return view(request, *args, **kwargs)
return view_or_redirect
我们使用了一些简单的中间件来根据必须处于 HTTPS 模式的基本 url 列表检查 url ,所有其他的都强制使用 HTTP 模式。这里最大的警告是,除非您格外小心,否则任何 POST 数据都可能丢失(在我们的案例中这无关紧要)。我们在需要信用卡号等的连接页面上执行此操作,因此一旦它们进入该管道,我们就强制它们使用 HTTPS。