2016-05-24 7 views
1

Ich schreibe meine App mit Play Framework v. 2.5.3 und benutze CSRF-Schutz wie in der offiziellen Dokumentation beschrieben.Play 2.5 disable csrf protection für einige Anfragen

Natürlich funktioniert es, solange alle Anfragen gefiltert werden müssen, aber einige von ihnen sollten umgangen werden. Wie können Filter konfiguriert werden, um Anforderungen an eine bestimmte Route zu umgehen? Danke für Ihre Hilfe!

+1

Es gibt noch ein Problem, das CSRF für bestimmte Routen deaktiviert: https://github.com/playframework/playframework/issues/5882 – adis

Antwort

2

Sie können CSRFFilter dekorieren und eine Liste von Routenpfaden verwenden, um die Anwendung des Filters ein- oder auszuschließen.

Die Routenweg müssen in der kompilierten Form sein, so dass eine Route, wie '/ foo/bar' /profile würde aber eine Route mit dynamischen Komponenten wie /view/:foo/:bar/view/$foo<[^/]+>/$bar<[^/]+> wird sein. Sie können die kompilierten Versionen der Routen auflisten, indem Sie im Entwicklungsmodus eine nicht zugeordnete URL aufrufen (z. B.).

import java.util.LinkedList; 
import java.util.List; 
import javax.inject.Inject; 
import akka.util.ByteString; 
import play.filters.csrf.CSRFFilter; 
import play.libs.streams.Accumulator; 
import play.mvc.EssentialAction; 
import play.mvc.EssentialFilter; 
import play.mvc.Result; 
import play.routing.Router; 

public class MaybeCsrfFilter extends EssentialFilter { 

    private final EssentialFilter csrfFilter; 

    private final List<String> applyCsrf = new LinkedList<>(); 

    @Inject 
    public MaybeCsrfFilter(final CSRFFilter csrfFilter) { 
     this.csrfFilter = csrfFilter.asJava(); 

     // alternatively, define the inclusion/exclusion list in the config and inject Configuration to obtain it 
     applyCsrf.add("/foo/bar"); 
     applyCsrf.add("/view/$foo<[^/]+>/$bar<[^/]+>"); 
    } 

    @Override 
    public EssentialAction apply(final EssentialAction next) { 
     return EssentialAction.of(request -> { 
      final Accumulator<ByteString, Result> accumulator; 
      final String currentRoute = request.tags().get(Router.Tags.ROUTE_PATTERN); 
      if (applyCsrf.contains(currentRoute)) { 
       accumulator = csrfFilter.apply(next).apply(request); 
      } else { 
       accumulator = next.apply(request); 
      } 
      return accumulator; 
     }); 
    } 
} 

Es ist rohe Gewalt, und Sie haben Ihre Filter synchron mit der Ein-/Ausschlussliste zu halten, aber es funktioniert.

Alternativ können Sie Kommentare in der Datei routes verwenden, um zu bestimmen, auf welchen Routen der CSRF-Filter nicht angewendet werden soll.

Für eine routes Datei wie

#NOCSRF 
GET /foo/bar    controllers.Application.foo() 
#NOCSRF 
GET /view/:hurdy/:gurdy controllers.Application.bar() 
GET /something/else  controllers.Application.bar() 

Dieser Filter Implementierung wird die CSRF-Filter auf jede Aktion, deren Weg durch # NOCSRF keine Anwendung voraus. In diesem Beispiel wird nur der Filter CSRF auf /something/else angewendet.

public EssentialAction apply(final EssentialAction next) { 
    return EssentialAction.of(request -> { 
     final Accumulator<ByteString, Result> accumulator; 
     final String routeComment = request.tags().get(Router.Tags.ROUTE_COMMENTS); 
     if ("NOCSRF".equals(routeComment)) { 
      accumulator = next.apply(request); 
     } else { 
      accumulator = csrfFilter.apply(next).apply(request); 
     } 
     return accumulator; 
    }); 
} 

Ihre Filters Definition dann wird

public class Filters implements HttpFilters { 

    private final MaybeCsrfFilter csrf; 

    @Inject 
    public Filters(final MaybeCsrfFilter csrf) { 
     this.csrf = csrf; 
    } 

    @Override 
    public EssentialFilter[] filters() { 
     return new EssentialFilter[]{csrf}; 
    } 
} 

keine bindende für MaybeCsrfFilter erstellen Vergessen!

+0

Dies ist viel schöner als der Vorschlag des Spiels, einen supergeheimen csrf-Ausnahme-Cookie zu erstellen – kdazzle