apache 如何强制对我的 Django 应用程序的某些 URL 使用 SSL?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1548210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to force the use of SSL for some URL of my Django Application?
提问by Natim
I want to be sure that for some URL of my website, SSL will be use. I saw a lot of answer already on SO.
我想确保对于我网站的某些 URL,将使用 SSL。我已经在 SO 上看到了很多答案。
Force redirect to SSL for all pages apart from one
So I think I will use mod_rewrite.
所以我想我会使用mod_rewrite.
My question is more about how to configure the Virtual Hostto run my Django Applicationover HTTPand over HTTPSwithout problems. I am using WSGI.
我的问题更多是关于如何配置虚拟主机以一遍又一遍地运行我的Django 应用程序HTTP而HTTPS不会出现问题。我正在使用WSGI.
Is it a problem to just duplicate the configuration over *:443and over *:80?
What should I do to have the best configuration?
一遍*:443又一遍地复制配置是否有问题*:80?我应该怎么做才能拥有最佳配置?
采纳答案by Graham Dumpleton
If by WSGI you actually mean Apache/mod_wsgi, then although mounted WSGI applications normally get run in their own sub interpreters, the 80/443 split is a special case and even though in different VirtualHost so long as mount point for WSGIScriptAlias, and the ServerName are the same, they will be merged.
如果 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>
This will happen for daemon mode as well, but with daemon mode you need to define only a single daemon process group in first VirtualHost definition and then just refer to that from both with WSGIProcessGroup.
守护进程模式也会发生这种情况,但是在守护进程模式下,您只需要在第一个 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>
The WSGIProcessGroup can only reach across like to that VirtualHost for same ServerName.
WSGIProcessGroup 只能到达同一个 ServerName 的 VirtualHost。
Django provides a is_secure() method for determining when request came via HTTPS which derives from WSGI variable with request called 'wsgi.url_scheme' which is set by mod_wsgi.
Django 提供了一个 is_secure() 方法来确定请求何时来自 HTTPS,该方法源自 WSGI 变量,请求名为“wsgi.url_scheme”,由 mod_wsgi 设置。
So, you would have one single Django WSGI script file and settings file. You just need to duplicate application mounting as decsribed in Apache/mod_wsgi configuration.
因此,您将拥有一个 Django WSGI 脚本文件和设置文件。您只需要按照 Apache/mod_wsgi 配置中的描述复制应用程序安装。
回答by Chip Tol
Besides using mod_rewrite, you can also use Django to control the SSL redirects.
除了使用 mod_rewrite,您还可以使用 Django 来控制 SSL 重定向。
Here's a modified version of a middleware from the Satchmo Project. I tend to like this method better than mod_rewrite as it's easier to manage.
这是来自Satchmo 项目的中间件的修改版本。我倾向于比 mod_rewrite 更喜欢这种方法,因为它更容易管理。
To use it, pass 'SSL':True into your url conf:
要使用它,请将 'SSL':True 传递到您的 url conf 中:
urlpatterns = patterns('some_site.some_app.views',
(r'^test/secure/$','test_secure',{'SSL':True}),
)
Here's the middleware code:
下面是中间件代码:
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)
回答by Wilfred Hughes
Here's a view decorator that you can apply to the views that should have HTTPS.
这是一个视图装饰器,您可以将其应用于应该具有 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
回答by Peter Rowell
We used some simple middleware to check urls against a list of base urls that mustbe in HTTPS mode, all others are forced to HTTP mode. The big caveat here is that any POST data can be lost unless you take extra care (it didn't matter in our case). We were doing this on join pages that required credit card numbers and the like so as soon as they were in that pipeline we forced them into HTTPS.
我们使用了一些简单的中间件来根据必须处于 HTTPS 模式的基本 url 列表来检查 url ,所有其他的都被强制为 HTTP 模式。这里需要注意的是,除非您格外小心,否则任何 POST 数据都可能丢失(在我们的情况下无关紧要)。我们在需要信用卡号等的加入页面上这样做,所以一旦他们在那个管道中,我们就强迫他们进入 HTTPS。

