2014-09-13 02:50:36 +08:00
|
|
|
import re
|
|
|
|
|
|
|
|
from django.conf import settings
|
|
|
|
from django.http import HttpResponsePermanentRedirect
|
2015-11-07 23:12:37 +08:00
|
|
|
from django.utils.deprecation import MiddlewareMixin
|
2014-09-13 02:50:36 +08:00
|
|
|
|
|
|
|
|
2015-11-07 23:12:37 +08:00
|
|
|
class SecurityMiddleware(MiddlewareMixin):
|
2021-01-13 03:55:32 +08:00
|
|
|
def __init__(self, get_response):
|
2020-08-25 04:25:33 +08:00
|
|
|
super().__init__(get_response)
|
2014-09-13 02:50:36 +08:00
|
|
|
self.sts_seconds = settings.SECURE_HSTS_SECONDS
|
|
|
|
self.sts_include_subdomains = settings.SECURE_HSTS_INCLUDE_SUBDOMAINS
|
2016-07-29 00:48:07 +08:00
|
|
|
self.sts_preload = settings.SECURE_HSTS_PRELOAD
|
2014-09-13 02:50:36 +08:00
|
|
|
self.content_type_nosniff = settings.SECURE_CONTENT_TYPE_NOSNIFF
|
|
|
|
self.redirect = settings.SECURE_SSL_REDIRECT
|
|
|
|
self.redirect_host = settings.SECURE_SSL_HOST
|
|
|
|
self.redirect_exempt = [re.compile(r) for r in settings.SECURE_REDIRECT_EXEMPT]
|
2019-03-22 05:33:41 +08:00
|
|
|
self.referrer_policy = settings.SECURE_REFERRER_POLICY
|
2020-08-27 00:09:19 +08:00
|
|
|
self.cross_origin_opener_policy = settings.SECURE_CROSS_ORIGIN_OPENER_POLICY
|
2014-09-13 02:50:36 +08:00
|
|
|
|
|
|
|
def process_request(self, request):
|
|
|
|
path = request.path.lstrip("/")
|
|
|
|
if (self.redirect and not request.is_secure() and
|
|
|
|
not any(pattern.search(path)
|
|
|
|
for pattern in self.redirect_exempt)):
|
|
|
|
host = self.redirect_host or request.get_host()
|
|
|
|
return HttpResponsePermanentRedirect(
|
|
|
|
"https://%s%s" % (host, request.get_full_path())
|
|
|
|
)
|
|
|
|
|
|
|
|
def process_response(self, request, response):
|
|
|
|
if (self.sts_seconds and request.is_secure() and
|
2018-10-30 06:19:04 +08:00
|
|
|
'Strict-Transport-Security' not in response):
|
2014-09-13 02:50:36 +08:00
|
|
|
sts_header = "max-age=%s" % self.sts_seconds
|
|
|
|
if self.sts_include_subdomains:
|
|
|
|
sts_header = sts_header + "; includeSubDomains"
|
2016-07-29 00:48:07 +08:00
|
|
|
if self.sts_preload:
|
|
|
|
sts_header = sts_header + "; preload"
|
2020-07-14 19:32:24 +08:00
|
|
|
response.headers['Strict-Transport-Security'] = sts_header
|
2014-09-13 02:50:36 +08:00
|
|
|
|
2017-11-14 05:15:49 +08:00
|
|
|
if self.content_type_nosniff:
|
2020-07-14 19:32:24 +08:00
|
|
|
response.headers.setdefault('X-Content-Type-Options', 'nosniff')
|
2014-09-13 02:50:36 +08:00
|
|
|
|
2019-03-22 05:33:41 +08:00
|
|
|
if self.referrer_policy:
|
|
|
|
# Support a comma-separated string or iterable of values to allow
|
|
|
|
# fallback.
|
2020-07-14 19:32:24 +08:00
|
|
|
response.headers.setdefault('Referrer-Policy', ','.join(
|
2019-03-22 05:33:41 +08:00
|
|
|
[v.strip() for v in self.referrer_policy.split(',')]
|
|
|
|
if isinstance(self.referrer_policy, str) else self.referrer_policy
|
|
|
|
))
|
|
|
|
|
2020-08-27 00:09:19 +08:00
|
|
|
if self.cross_origin_opener_policy:
|
|
|
|
response.setdefault(
|
|
|
|
'Cross-Origin-Opener-Policy',
|
|
|
|
self.cross_origin_opener_policy,
|
|
|
|
)
|
2014-09-13 02:50:36 +08:00
|
|
|
return response
|