add Strict-Transport-Security header #19861

fix the signature of Strict-Transport-Security header #19861

parse strict-transport-security header with the max-age directive only #19861

parse includeSubDomains directive #19861

add doc on Stict-Transport-Security #19861

fix punctuation in doc on Stict-Transport-Security #19861
This commit is contained in:
Martin Miklós 2016-02-25 22:09:32 +01:00
parent 06b4d54960
commit 78ad0c63d3
6 changed files with 55 additions and 0 deletions

View file

@ -282,6 +282,16 @@ Connection
request's method, protocol and potential ``Connection`` header as well as the response's protocol, entity and
potential ``Connection`` header. See `this test`__ for a full table of what happens when.
Strict-Transport-Security
HTTP Strict Transport Security (HSTS) is a web security policy mechanism which is communicated by the
``Strict-Transport-Security`` header. The most important security vulnerability that HSTS can fix is SSL-stripping
man-in-the-middle attacks. The SSL-stripping attact works by transparently converting a secure HTTPS connection into a
plain HTTP connection. The user can see that the connection is insecure, but crucially there is no way of knowing
whether the connection should be secure. HSTS addresses this problem by informing the browser that connections to the
site should always use TLS/SSL. See also `RFC 6797`_.
.. _RFC 6797: http://tools.ietf.org/html/rfc6797
__ @github@/akka-http-core/src/test/scala/akka/http/impl/engine/rendering/ResponseRendererSpec.scala#L422
Custom Headers

View file

@ -0,0 +1,21 @@
/**
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package akka.http.javadsl.model.headers;
/**
* Model for the `Strict-Transport-Security` header.
* Specification: https://tools.ietf.org/html/rfc6797
*/
public abstract class StrictTransportSecurity extends akka.http.scaladsl.model.HttpHeader {
public abstract long maxAge();
public abstract boolean includeSubDomains();
public static StrictTransportSecurity create(long maxAge) {
return new akka.http.scaladsl.model.headers.Strict$minusTransport$minusSecurity(maxAge, false);
}
public static StrictTransportSecurity create(long maxAge, boolean includeSubDomains) {
return new akka.http.scaladsl.model.headers.Strict$minusTransport$minusSecurity(maxAge, includeSubDomains);
}
}

View file

@ -150,6 +150,7 @@ private[http] object HeaderParser {
"sec-websocket-protocol",
"sec-websocket-version",
"set-cookie",
"strict-transport-security",
"transfer-encoding",
"upgrade",
"user-agent",

View file

@ -186,6 +186,10 @@ private[parser] trait SimpleHeaders { this: Parser with CommonRules with CommonA
// http://tools.ietf.org/html/rfc7231#section-7.4.2
def server = rule { products ~ EOI ~> (Server(_)) }
def `strict-transport-security` = rule {
ignoreCase("max-age=") ~ `delta-seconds` ~ optional(ws(";") ~ ignoreCase("includesubdomains") ~ push(true)) ~ EOI ~> (`Strict-Transport-Security`(_, _))
}
// http://tools.ietf.org/html/rfc7230#section-3.3.1
def `transfer-encoding` = rule {
oneOrMore(`transfer-coding`).separatedBy(listSep) ~ EOI ~> (`Transfer-Encoding`(_))

View file

@ -791,6 +791,19 @@ final case class Server(products: immutable.Seq[ProductVersion]) extends jm.head
def getProducts: Iterable[jm.headers.ProductVersion] = products.asJava
}
// https://tools.ietf.org/html/rfc6797
object `Strict-Transport-Security` extends ModeledCompanion[`Strict-Transport-Security`] {
def apply(maxAge: Long, includeSubDomains: Option[Boolean]) = new `Strict-Transport-Security`(maxAge, includeSubDomains.getOrElse(false))
}
final case class `Strict-Transport-Security`(maxAge: Long, includeSubDomains: Boolean = false) extends jm.headers.StrictTransportSecurity with ResponseHeader {
def renderValue[R <: Rendering](r: R): r.type = {
r ~~ "max-age=" ~~ maxAge
if (includeSubDomains) r ~~ "; includeSubDomains"
r
}
protected def companion = `Strict-Transport-Security`
}
// https://tools.ietf.org/html/rfc6265
object `Set-Cookie` extends ModeledCompanion[`Set-Cookie`]
final case class `Set-Cookie`(cookie: HttpCookie) extends jm.headers.SetCookie with ResponseHeader {

View file

@ -386,6 +386,12 @@ class HttpHeaderSpec extends FreeSpec with Matchers {
"Server: as fghf.fdf/xx" =!= `Server`(Vector(ProductVersion("as"), ProductVersion("fghf.fdf", "xx")))
}
"Strict-Transport-Security" in {
"Strict-Transport-Security: max-age=31536000" =!= `Strict-Transport-Security`(maxAge = 31536000)
"Strict-Transport-Security: max-age=31536000" =!= `Strict-Transport-Security`(maxAge = 31536000, includeSubDomains = false)
"Strict-Transport-Security: max-age=31536000; includeSubDomains" =!= `Strict-Transport-Security`(maxAge = 31536000, includeSubDomains = true)
}
"Transfer-Encoding" in {
"Transfer-Encoding: chunked" =!= `Transfer-Encoding`(TransferEncodings.chunked)
"Transfer-Encoding: gzip" =!= `Transfer-Encoding`(TransferEncodings.gzip)