问题
I'm working on a project that uses Google Cloud Platform's App Engine in the Python 3 Flexible Environment using Django, and I'm trying to permanently redirect all requests over http
to https
for all routes, but so far have not been successful. I can access the site over https
, but only if explicitly written in the address bar.
I've looked at this post: How to permanently redirect `http://` and `www.` URLs to `https://`? but did not find the answer useful.
The app works properly in every sense except for the redirecting. Here is my app.yaml
file:
# [START runtime]
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT myproject.wsgi
runtime_config:
python_version: 3
# [END runtime]
In myproject/settings.py
I have these variables defined:
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_PROXY_SSL_HEADER = ('HTTP-X-FORWARDED-PROTO', 'https')
On my local machine, when I set SECURE_SSL_REDIRECT
to True
, I was redirected to https
properly, even though SSL is not supported on localhost. In production, I am still able to access the site using just http
.
Is there something I'm missing or doing wrong to cause the redirect not to happen?
回答1:
Setting secure
in app.yaml only works for GAE Standard but not in Flexible. The app.yaml docs for Flexible do not mention this key at all.
You will probably have to do it on application level by inspecting the value of the X-Forwarded-Proto
header. It will be set to https
if the request to your app came by HTTPS. You can find more info on environment-provided headers in Flexible environment in the docs here.
回答2:
Make sure you have SecurityMiddleware
and CommonMiddleware
enabled, and assign a Base_URL
:
settings.py
:
MIDDLEWARE_CLASSES = (
...
'django.middleware.security.SecurityMiddleware'
'django.middleware.common.CommonMiddleware',
)
BASE_URL = 'https://www.example.com'
Or, you could write your own middleware:
MIDDLEWARE_CLASSES = (
...
'core.my_middleware.ForceHttps',
)
BASE_URL = 'https://www.example.com'
my_middleware.py
:
from django.http import HttpResponsePermanentRedirect
class ForceHttps(object):
def process_request(self, request):
if not (request.META.get('HTTPS') == 'on' and settings. BASE_URL == 'https://' + request.META.get('HTTP_HOST') ):
return HttpResponsePermanentRedirect(settings. BASE_URL + request.META.get('PATH_INFO'))
else:
return None
回答3:
The issue is the header name. When accessing Django through a WSGI server, you should use the X-Forwarded-Proto
header instead of the HTTP_X_FORWARDED_PROTO
.
See: Why does django ignore HTTP_X_FORWARDED_PROTO from the wire but not in tests?
回答4:
I had a similar problem and tried a number changes both in the app.yaml and also in settings.py for a custom domain (with the default ssl cert supplied by GAE).
Through trial and error I found that in settings.py updating the allowed hosts to the appropriate domains had the desired result:
ALLOWED_HOSTS = ['https://{your-project-name}.appspot.com','https://www.yourcustomdomain.com']
Update: I am no longer sure the above is the reason as on a subsequent deploy the above was rejected and I was getting a hosts error. However the redirect is still in place... :(
Before this change I was able to switch between http:// and https:// manually in the address bar now it redirects automaticlly.
来源:https://stackoverflow.com/questions/52029939/permanently-redirect-http-to-https-on-google-app-engine-flexible-with-django