Content security policy (CSP)

The CSP is a security feature that helps prevent cross-site scripting (XSS), clickjacking, and other code injection attacks resulting from execution of malicious content in the trusted web page context. One way to implement CSP is to add a Content-Security-Policy HTTP header to your web server responses. The header value is a string that defines the policy. The policy is a set of directives that specify the content sources that the browser should consider acceptable for the web page. The browser will only execute or render resources from those sources. For example, the following CSP header specifies that the browser should only load resources from the same origin as the web page, and should not execute inline scripts or styles. When the browser receives this header, it will enforce the policy by blocking any resources that do not comply with the specified directives. When ressources from other origins are needed, the links to these ressources have to be mentioned explicitly. For Django, a package called django-csp is available to help you implement CSP in your Django project. To add a link, which is considered as a trusted source, it has to be added to the 01_application/webcentral_app/webcentral_app/settings.py file in the CSP_SCRIPT_SRC and CSP_STYLE_SRC lists. The following code shows trusted sources for scripts and styles:

CSP_SCRIPT_SRC = (
    "'self'",
    "https://ajax.googleapis.com",
    "https://cdnjs.cloudflare.com",
    "https://maxcdn.bootstrapcdn.com",
    "https://cdn.plot.ly",
    "https://unpkg.com",
    "https://code.highcharts.com/highcharts.js",
    "https://cdn.jsdelivr.net/gh/harvesthq/chosen@1.8.7/chosen.jquery.min.js",
)

CSP_STYLE_SRC = (
    "'self'",
    "https://maxcdn.bootstrapcdn.com",
    "https://cdnjs.cloudflare.com",
    "https://cdn.plot.ly",
    "https://unpkg.com",
    "https://cdn.jsdelivr.net/gh/harvesthq/chosen@1.8.7/chosen.min.css",
)

Solving browser caching issues

When developing the application in an agile manner lots of changes will be introduced to the web application when its already running publicly. Because of that problems can arise. One problem has to do with the client browser caches static files (javascript/stylesheet-files) to reduce loading time. This can lead to websites look broken for clients re-visiting the website since the still use the old cached versions. To address that problem a static files bundler webpack is used. It transpiles the scss-files into one css-file. A hash-value is also put into the filename. The also installed package wepback-bundler-tracker creates a file weback-stats.json where the location of the created css-files is stored. The stats file is then used by the package django-weback-loader to insert the most up-to-date file in stylesheet link tag in the django templates.

The configuration of django-weback-loader is done in the settings.py-file. There, the following lines were added:

WEBPACK_LOADER = {
    'DEFAULT': {
        'BUNDLE_DIR_NAME': '/webpack_bundles/',
        'CACHE': not DEBUG,
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
        'POLL_INTERVAL': 0.1,
        'IGNORE': [r'.+\.hot-update.js', r'.+\.map'],
    }
}

The location of the transpiled bundles are specified in the BUNDLE_DIR_NAME constant. The location specified must be reachable from within the location specified in the STATICFILES_DIR constant. The location of the webpack-bundler-loader stats-file is specfied in STATS_FILE. A absolute path is taken as input. Furthermore the intervall in which changes in the stats file are checked can be set via POLL_INTERVAL in seconds. Polling is only activated if the django DEBUG-flag is set to true. DEBUG beeing True typically means that django is executed in a development environment, and DEBUG equals False is set on a production instance.