7

In Play 2.3 kann ich bestimmte Filter basierend auf unterschiedlichen Anforderungswegen oder Methoden deaktivieren. Ich finde jedoch keinen Weg, dies in Play 2.4 zu tun. https://www.playframework.com/documentation/2.4.x/ScalaHttpFilters. Wie erreiche ich ein ähnliches Ergebnis in Play 2.4 HttpFilters?Abspielen 2.4 bestimmte Filter deaktivieren, die auf Anforderungspfad oder Methode festgelegt sind

Hier ist, wie ich es in Play 2.3 gemacht habe.

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) 
    } 

} 

Es gibt keine Request in HttpFilters im Play 2,4

class Filters @Inject() (
    securityHeadersFilter: SecurityHeadersFilter, 
    cacheCtrlHeadersFilter: CacheCtrlHeadersFilter 
) extends HttpFilters { 

    val filters = Seq(securityHeadersFilter, cacheCtrlHeadersFilter) 
} 
+1

Nur ein Gedanke, aber vielleicht können Sie den Filter erweitern und die Logik dort einbauen? – gpgekko

+1

@gpgekko Ja, ich habe darüber nachgedacht. Aber ich frage mich, ob dies die einzige Lösung ist. – angelokh

+1

@gpgekko Wie kann ich den aktuellen Filter in der Anwendungsfunktion überspringen, wenn ich einen Filter erstelle? – angelokh

Antwort

2

Dies ist, was ich getan habe.

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
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

Können Sie bitte Ihre Antwort erklären? Wie kann ich einen Filter in der von Ihnen bereitgestellten Methode überspringen? – angelokh

+1

Bitte sehen Sie meine Implementierung: In meinem Projekt hat es auch einen Filter. Ich habe die Zustandsüberprüfung in meinen Filter eingefügt. Zum Beispiel: CoreActionFilter. Sie könnten versuchen, die Methode apply zu implementieren, um die Bedingungsprüfung durchzuführen. – Birdflying1005

2

Meine Implementierung verfügbar:

Klasse Filter @Inject() (corsFilter: CORSFilter, coreActionFilter: CoreActionFilter) erweitert HttpFilters { Def Filter = Seq (CorsFilter, CoreActionFilter) }

Klasse CoreActionFilter erweitert Filter { def gelten (nextFilter: Request => Future [Ergebnis]) (Request: Request) = {

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) 

} }

+0

Bitte bearbeiten Sie Ihre vorherige Antwort, wenn Sie etwas hinzufügen möchten, anstatt eine neue Antwort zu posten – gpgekko

1

Dies ist, wie ich implementiert. Es funktioniert, aber nicht ideal. Grundsätzlich fügen wir einen äußersten WhiteListFilter hinzu, um die Anfrage anzureichern, so dass die Anfrage niemals herausgefiltert wird.

Wenn der Filter über die Manipulation der Antwort ist, kann derselbe Filter verwendet werden, um die Antwort effektiv unset.

Haftungsausschluss, ich tippte folgenden Code mit einem Texteditor nur für Sie, um ein Bild zu bekommen. Kann nicht garantieren, dass es kompiliert:

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 
      } 
     } 
    } 
    } 
} 
Verwandte Themen