Play 2.5 对某些请求禁用 csrf 保护 [英] Play 2.5 disable csrf protection for some requests
问题描述
我正在使用 play 框架 v. 2.5.3 编写我的应用,并使用官方文档中描述的 CSRF 保护.
I'm writing my app using play framework v. 2.5.3 and use CSRF protection as it is described in official documentation.
public class Filters implements HttpFilters {
@Inject
CSRFFilter csrfFilter;
@Override
public EssentialFilter[] filters() {
return new EssentialFilter[]{csrfFilter.asJava()};
}}
当然可以,只要所有的请求都需要过滤,但其中一些应该绕过.如何配置过滤器以绕过对某些指定路由的请求?谢谢你的帮助!
Of course, it works, as long as all of requests need to be filtered, but some of them should be bypassed. How can filters be configured to bypass requests to some specified route? Thanks for your help!
推荐答案
您可以修饰 CSRFFilter
并使用路由路径列表来包含或排除过滤器的应用程序.
You can decorate CSRFFilter
and use a list of route paths to either include or exclude the application of the filter.
路由路径需要采用编译后的形式,因此像‘/foo/bar’这样的路由将是 /profile
但具有像 /view/这样的动态组件的路由:foo/:bar
变成 /view/$foo<[^/]+>/$bar<[^/]+>
.在开发模式下,您可以通过访问未映射的 URL(例如 http://localhost:9000/@foo
)来列出路由的编译版本.
The route paths will need to be in the compiled form, so a route like ´/foo/bar´ would be /profile
but a route with dynamic components like /view/:foo/:bar
becomes /view/$foo<[^/]+>/$bar<[^/]+>
. You can list the compiled versions of the routes by going to an unmapped URL (e.g. http://localhost:9000/@foo
) when in development mode.
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;
});
}
}
这是蛮力,您必须使过滤器与包含/排除列表保持同步,但它确实有效.
It's brute force, and you have to keep your filters in sync with the inclusion/exclusion list, but it works.
或者,您可以使用 routes
文件中的注释来确定哪些路由不应应用 CSRF 过滤器.
Alternatively, you can use comments in the routes
file to determine which routes should not have the CSRF filter applied.
对于 routes
文件,如
#NOCSRF
GET /foo/bar controllers.Application.foo()
#NOCSRF
GET /view/:hurdy/:gurdy controllers.Application.bar()
GET /something/else controllers.Application.bar()
此过滤器实现不会将 CSRF 过滤器应用于其路由以 # NOCSRF
开头的任何操作.对于此示例,只有 /something/else
将应用 CSRF 过滤器.
This filter implementation will not apply the CSRF filter to any action whose route is preceded by # NOCSRF
. For this example, only /something/else
will have the CSRF filter applied to it.
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;
});
}
你的Filters
定义就变成了
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};
}
}
不要忘记为 MaybeCsrfFilter
创建绑定!
Don't forget to create a binding for MaybeCsrfFilter
!
这篇关于Play 2.5 对某些请求禁用 csrf 保护的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!