在Play 2.3中,我可以根据不同的请求路径或方法禁用某些过滤器。但是,我无法在Play 2.4中找到一种方法。 https://www.playframework.com/documentation/2.4.x/ScalaHttpFilters。如何在Play 2.4 HttpFilters中获得类似的结果。
以下是我在Play 2.3中的表现。
object CacheCtrlHeadersFilter extends EssentialFilter {
def apply(action: EssentialAction) = new EssentialAction {
def apply(requestHeader: RequestHeader) = {
action(requestHeader).map { result =>
result.withHeaders(
CACHE_CONTROL -> "no-cache, no-store, must-revalidate, private",
PRAGMA -> "no-cache"
)
}
}
}
}
import play.api.libs.iteratee._
object FilterChainByRequestHeader {
def apply[A](action: EssentialAction, filtersFun: (RequestHeader) => List[EssentialFilter]): EssentialAction = new EssentialAction {
def apply(rh: RequestHeader): Iteratee[Array[Byte], Result] = {
val chain = filtersFun(rh).reverse.foldLeft(action) { (a, i) => i(a) }
chain(rh)
}
}
}
object Global extends GlobalSettings {
val securityFilter = SecurityHeadersFilter()
val defaultFilters = List(securityFilter,
CacheCtrlHeadersFilter)
def filters(rh: RequestHeader) = {
if (rh.method == "OPTIONS") <----------- by method
defaultFilters.filterNot(_.eq(securityFilter))
else if (rh.path.startsWith("/apps/google")) <----------- by path
defaultFilters.filterNot(_.eq(securityFilter))
else defaultFilters
}
override def doFilter(a: EssentialAction): EssentialAction = {
FilterChainByRequestHeader(super.doFilter(a), filters)
}
}
Play 2.4中的HttpFilters中没有可用的RequestHeader
class Filters @Inject() (
securityHeadersFilter: SecurityHeadersFilter,
cacheCtrlHeadersFilter: CacheCtrlHeadersFilter
) extends HttpFilters {
val filters = Seq(securityHeadersFilter, cacheCtrlHeadersFilter)
}
答案 0 :(得分:3)
object Global extends WithFilters(new CoreActionFilter()) {
}
class CoreActionFilter extends Filter {
lazy val serviceLogger = Logger("services")
def apply(nextFilter: RequestHeader => Future[Result])(requestHeader: RequestHeader) = {
nextFilter(requestHeader).map { result =>
val action = requestHeader.path match {
case "/favicon.ico" => s"[ ${requestHeader.remoteAddress.toString}]"
case _ => s"[ ${requestHeader.remoteAddress.toString}]" + ("[") + requestHeader.tags(Tags.RoutePattern) + ("]") + ("[") + requestHeader.tags(Tags.RouteController) + "." + requestHeader.tags(Tags.RouteActionMethod) + ("]")
}
val startTime = System.currentTimeMillis
val endTime = System.currentTimeMillis
val requestTime = endTime - startTime
val token = requestHeader.headers.get("X-Auth-Token")
serviceLogger.info(s"[$token]" + s"${action}[${requestTime}ms]" + s"[${result.header.status}]")
result.withHeaders("Request-Time" -> requestTime.toString)
}(CoreContexts.simpleSqlQuery)
}
}
答案 1 :(得分:2)
我的实施:
类过滤器@Inject()(corsFilter:CORSFilter,coreActionFilter:CoreActionFilter)扩展了HttpFilters { def filters = Seq(corsFilter,coreActionFilter) }
类CoreActionFilter扩展Filter { def apply(nextFilter:RequestHeader =&gt; Future [Result])(requestHeader:RequestHeader)= {
if(/*yourContidion*/) {
nextFilter(requestHeader).map { result =>
val action = requestHeader.path match {
case "/favicon.ico" => s"[ ${requestHeader.remoteAddress.toString}]"
case _ => s"[ ${requestHeader.remoteAddress.toString}]" + ("[") + requestHeader.tags(Tags.RoutePattern) + ("]") + ("[") + requestHeader.tags(Tags.RouteController) + "." + requestHeader.tags(Tags.RouteActionMethod) + ("]")
}
val startTime = System.currentTimeMillis
val endTime = System.currentTimeMillis
val requestTime = endTime - startTime
val token = requestHeader.headers.get("X-Auth-Token")
serviceLogger.info(s"[$token]" + s"${action}[${requestTime}ms]" + s"[${result.header.status}]")
result.withHeaders("Request-Time" -> requestTime.toString)
}(CoreContexts.simpleSqlQuery)
}
nextFilter(requestHeader)
} }
答案 2 :(得分:2)
这就是我最终要做的事情。
class SecurityHeadersFilter extends EssentialFilter {
def apply(action: EssentialAction) = new EssentialAction {
def apply(rh: RequestHeader) = {
action(rh).map { result =>
if (rh.method != "OPTIONS" && !rh.path.startsWith("/apps/google"))
result.withHeaders(
"X-Frame-Options" -> "SAMEORIGIN",
"Content-Security-Policy" -> "default-src * 'self' 'unsafe-inline' 'unsafe-eval' "
)
}
}
}
}
class Filters @Inject() (
gzip: GzipFilter,
cache: CacheCtrlHeadersFilter,
cors: CorsFilter,
security: SecurityHeadersFilter
) extends HttpFilters {
val filters = Seq(gzip, cache, cors, security)
}
答案 3 :(得分:1)
这是我实施的方式。它工作,但不理想。基本上我们添加一个最外层的WhiteListFilter来丰富请求,以便永远不会过滤掉请求。
如果过滤器是关于操纵响应,则可以使用相同的过滤器有效地unset
响应。
免责声明,我使用文本编辑器输入以下代码,仅供您查看照片。不能保证它编译:
object WhiteListFilter extends EssentialFilter {
override def apply(next: EssentialAction) = new EssentialAction {
override def apply(req: RequestHeader) = {
val whiteListedReq =
// if the filter is about to block some request by headers
// then append the valid headers, to `whitelist` request
if (req.method == "OPTIONS") {
req.copy(headers = req.headers.add("XXX" -> "XXX"))
} else {
req
}
next(whiteListedReq).map {
resp =>
// if the filter is about to manipulate response
// then unset the actions
if (req.method == "OPTIONS") {
val headers = resp.headers - "key1" - "key2"
resp.copy(headers = headers)
} else {
resp
}
}
}
}
}