|
Play Framework/Scala example source code file (SecurityHeadersFilter.scala)
The SecurityHeadersFilter.scala Play Framework example source code/* * Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com> */ package play.filters.headers import play.api.mvc._ import scala.concurrent.Future import play.api.Configuration /** * This class sets a number of common security headers on the HTTP request. * * NOTE: Because these are security headers, they are "secure by default." If the filter is applied, but these * fields are NOT defined in Configuration, the defaults on the filter are NOT omitted, but are instead * set to the strictest possible value. * * <ul> * <li>{{play.filters.headers.frameOptions}} - sets frameOptions. Some("DENY") by default. * <li>{{play.filters.headers.xssProtection}} - sets xssProtection. Some("1; mode=block") by default. * <li>{{play.filters.headers.contentTypeOptions}} - sets contentTypeOptions. Some("nosniff") by default. * <li>{{play.filters.headers.permittedCrossDomainPolicies}} - sets permittedCrossDomainPolicies. Some("master-only") by default. * <li>{{play.filters.headers.contentSecurityPolicy}} - sets contentSecurityPolicy. Some("default-src 'self'") by default. * </ul> * * @see <a href="https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options">X-Frame-Options</a> * @see <a href="http://blogs.msdn.com/b/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx">X-Content-Type-Options</a> * @see <a href="http://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-iv-the-xss-filter.aspx">X-XSS-Protection</a> * @see <a href="http://www.html5rocks.com/en/tutorials/security/content-security-policy/">Content-Security-Policy</a> * @see <a href="http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html">Cross Domain Policy File Specification</a> */ object SecurityHeadersFilter { val X_FRAME_OPTIONS_HEADER = "X-Frame-Options" val X_XSS_PROTECTION_HEADER = "X-XSS-Protection" val X_CONTENT_TYPE_OPTIONS_HEADER = "X-Content-Type-Options" val X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER = "X-Permitted-Cross-Domain-Policies" val CONTENT_SECURITY_POLICY_HEADER = "Content-Security-Policy" val DEFAULT_FRAME_OPTIONS = "DENY" val DEFAULT_XSS_PROTECTION = "1; mode=block" val DEFAULT_CONTENT_TYPE_OPTIONS = "nosniff" val DEFAULT_PERMITTED_CROSS_DOMAIN_POLICIES = "master-only" val DEFAULT_CONTENT_SECURITY_POLICY = "default-src 'self'" /** * Convenience method for creating a SecurityHeadersFilter that reads settings from application.conf. Generally speaking, * you'll want to use this or the apply(SecurityHeadersConfig) method. * * @return a configured SecurityHeadersFilter. */ def apply(): SecurityHeadersFilter = { new SecurityHeadersFilter() } /** * Convenience method for creating a filter using play.api.Configuration. Good for testing. * * @param config a configuration object that may contain string settings. * @return a configured SecurityHeadersFilter. */ def apply(config: Configuration): SecurityHeadersFilter = { apply(new SecurityHeadersParser().parse(config)) } /** * Convenience method for creating a filter using SecurityHeadersConfig case class. Use this if you have settings * that you want to specifically turn off by setting to None. * * @param securityHeaderConfig * @return */ def apply(securityHeaderConfig: => SecurityHeadersConfig): SecurityHeadersFilter = { new SecurityHeadersFilter(securityHeaderConfig) } } /** * SecurityHeaders trait. The default case class doesn't use it, but if you create a class which may return * different values based off the header and the result, this is where to start. */ trait SecurityHeadersConfig { def frameOptions: Option[String] def xssProtection: Option[String] def contentTypeOptions: Option[String] def permittedCrossDomainPolicies: Option[String] def contentSecurityPolicy: Option[String] } /** * A type safe configuration object for setting security headers. * * @param frameOptions "X-Frame-Options": * @param xssProtection "X-XSS-Protection": * @param contentTypeOptions "X-Content-Type-Options" * @param permittedCrossDomainPolicies "X-Permitted-Cross-Domain-Policies". * @param contentSecurityPolicy "Content-Security-Policy" */ case class DefaultSecurityHeadersConfig(frameOptions: Option[String], xssProtection: Option[String], contentTypeOptions: Option[String], permittedCrossDomainPolicies: Option[String], contentSecurityPolicy: Option[String]) extends SecurityHeadersConfig /** * Parses out a SecurityHeadersConfig from play.api.Configuration (usually this means application.conf). */ class SecurityHeadersParser { val FRAME_OPTIONS_CONFIG_PATH: String = "play.filters.headers.frameOptions" val XSS_PROTECTION_CONFIG_PATH: String = "play.filters.headers.xssProtection" val CONTENT_TYPE_OPTIONS_CONFIG_PATH: String = "play.filters.headers.contentTypeOptions" val PERMITTED_CROSS_DOMAIN_POLICIES_CONFIG_PATH: String = "play.filters.headers.permittedCrossDomainPolicies" val CONTENT_SECURITY_POLICY_CONFIG_PATH: String = "play.filters.headers.contentSecurityPolicy" def parse(config: Configuration): SecurityHeadersConfig = { import SecurityHeadersFilter._ val frameOptions: String = config.getString(FRAME_OPTIONS_CONFIG_PATH).getOrElse(DEFAULT_FRAME_OPTIONS) val xssProtection: String = config.getString(XSS_PROTECTION_CONFIG_PATH).getOrElse(DEFAULT_XSS_PROTECTION) val contentTypeOptions: String = config.getString(CONTENT_TYPE_OPTIONS_CONFIG_PATH).getOrElse(DEFAULT_CONTENT_TYPE_OPTIONS) val permittedCrossDomainPolicies: String = config.getString(PERMITTED_CROSS_DOMAIN_POLICIES_CONFIG_PATH).getOrElse(DEFAULT_PERMITTED_CROSS_DOMAIN_POLICIES) val contentSecurityPolicy: String = config.getString(CONTENT_SECURITY_POLICY_CONFIG_PATH).getOrElse(DEFAULT_CONTENT_SECURITY_POLICY) DefaultSecurityHeadersConfig( frameOptions = Option(frameOptions), xssProtection = Option(xssProtection), contentTypeOptions = Option(contentTypeOptions), permittedCrossDomainPolicies = Option(permittedCrossDomainPolicies), contentSecurityPolicy = Option(contentSecurityPolicy)) } } /** * The case class that implements the filter. This gives you the most control, but you may want to use the apply() * method on the companion singleton for convenience. */ class SecurityHeadersFilter(config: => SecurityHeadersConfig) extends Filter { private lazy val securityHeadersConfig: SecurityHeadersConfig = config /** * Zero argument constructor. This allows the Java GlobalSettings class to call this class and load configured * options from application.conf. * * @return a new configured instance of SecurityHeadersFilter. */ def this() = this(new SecurityHeadersParser().parse(play.api.Play.current.configuration)) /** * Applies the filter to an action, appending the headers to the result so it shows in the HTTP response. * * @param f the rawest form of Action. * @param rh the request header. * @return a result with the security headers included, using r.withHeaders. */ def apply(f: (RequestHeader) => Future[Result])(rh: RequestHeader): Future[Result] = { import play.api.libs.concurrent.Execution.Implicits.defaultContext import SecurityHeadersFilter._ val result = f(rh) result.map { r => val headers: Seq[(String, String)] = Seq( securityHeadersConfig.frameOptions.map(X_FRAME_OPTIONS_HEADER -> _), securityHeadersConfig.xssProtection.map(X_XSS_PROTECTION_HEADER -> _), securityHeadersConfig.contentTypeOptions.map(X_CONTENT_TYPE_OPTIONS_HEADER -> _), securityHeadersConfig.permittedCrossDomainPolicies.map(X_PERMITTED_CROSS_DOMAIN_POLICIES_HEADER -> _), securityHeadersConfig.contentSecurityPolicy.map(CONTENT_SECURITY_POLICY_HEADER -> _) ).flatten r.withHeaders(headers: _*) } } } Other Play Framework source code examplesHere is a short list of links related to this Play Framework SecurityHeadersFilter.scala source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.