简体   繁体   中英

How to redirect http://www.example.com to https://example.com with middleware

I got lost in deployment of my first django-application. The task I'm standing in front of is to redirect http://www to bare https://. The following is already working:

https://www » bare https://

bare http:// » bare https://

But if I just type in www. I land on the standard Ubuntu/Apache site.

middleware.py

from django.http import HttpResponsePermanentRedirect


class WwwRedirectMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        host = request.get_host().partition(':')[0]
        if host == "www.example.com":
            return HttpResponsePermanentRedirect(
                "https://example.com" + request.path
            )
        else:
            return self.get_response(request)

example.conf

 1 <VirtualHost *:80>
 10     ServerName  example.com
 11     ServerAdmin  marcel@example.com
 12     DocumentRoot /var/www/html

 31 RewriteEngine on
 32 RewriteCond %{SERVER_NAME} =example.com
 33 RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
 34 </VirtualHost>

example-le-ssl.conf

 1 <IfModule mod_ssl.c>
  2 <VirtualHost *:443>

 11         ServerName  example.com
 12         ServerAdmin  marcel@example.com
 13         DocumentRoot /var/www/html

 60 SSLCertificateFile /etc/letsencrypt/live/example.com-0001/fullchain.pem
 61 SSLCertificateKeyFile /etc/letsencrypt/live/example.com-0001/privkey.pem
 62 Include /etc/letsencrypt/options-ssl-apache.conf
 63 </VirtualHost>
 64 </IfModule>

This is what I get with curl

~$ curl -I http://example.com
HTTP/1.1 301 Moved Permanently
Date: Wed, 02 Dec 2020 08:03:02 GMT
Server: Apache/2.4.46 (Ubuntu)
Location: https://example.com/
Content-Type: text/html; charset=iso-8859-1

~$ curl -I http://www.example.com
HTTP/1.1 200 OK
Date: Wed, 02 Dec 2020 08:03:21 GMT
Server: Apache/2.4.46 (Ubuntu)
Last-Modified: Wed, 11 Nov 2020 22:26:44 GMT
ETag: "2aa6-5b3dc4a55bcd4"
Accept-Ranges: bytes
Content-Length: 10918
Vary: Accept-Encoding
Content-Type: text/html

~$ curl -I https://www.example.com
curl: (60) SSL: no alternative certificate subject name matches target host name 'www.example.com'
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

But the certificates seem to be correct:

~$  sudo certbot --apache -d example.com -d www.example.com

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache
Cert not yet due for renewal

You have an existing certificate that has exactly the same domains or certificate name you requested and isn't close to expiry.
(ref: /etc/letsencrypt/renewal/example.com.conf)

These may be two problems, but I do not know how to untangle them or if just one change could solve both...

This is something that apache will do before the django app needs to, one does not need add django middleware.

 <VirtualHost *:80>
      ServerName  example.com
      ServerAlias www.example.com
      ServerAdmin  marcel@example.com
      DocumentRoot /var/www/html

 RewriteEngine on
 RewriteCond %{HTTP_HOST} ^www\.
 RewriteRule ^ https://example.com%{REQUEST_URI} [END,NE,R=permanent]
 </VirtualHost>

As a second layer, in the settings.py set SECURE_SSL_REDIRECT = True

There is also the ./manage.py check --deploy management command to check and show all built in security settings.

*edit to show removal of the www in domain name.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM