【问题标题】:Play 2.5 disable csrf protection for some requestsPlay 2.5 对某些请求禁用 csrf 保护
【发布时间】:2016-09-21 08:29:40
【问题描述】:

我正在使用 play framework v. 2.5.3 编写我的应用程序,并使用官方文档中描述的 CSRF 保护。

public class Filters implements HttpFilters {

@Inject
CSRFFilter csrfFilter;

@Override
public EssentialFilter[] filters() {
    return new EssentialFilter[]{csrfFilter.asJava()};
}}

当然,只要需要过滤所有请求,它就可以工作,但其中一些应该被绕过。如何配置过滤器以绕过对某些指定路由的请求?谢谢你的帮助!

【问题讨论】:

标签: java playframework csrf playframework-2.5


【解决方案1】:

您可以装饰CSRFFilter 并使用路由路径列表来包含或排除过滤器的应用。

路由路径需要采用编译后的形式,因此像 '/foo/bar' 这样的路由将是 /profile,但带有动态组件的路由像 /view/:foo/:bar 会变成 /view/$foo<[^/]+>/$bar<[^/]+>。在开发模式下,您可以通过转到未映射的 URL(例如http://localhost:9000/@foo)来列出路由的编译版本。

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

这是蛮力的,您必须使您的过滤器与包含/排除列表保持同步,但它确实有效。

或者,您可以使用 routes 文件中的 cmets 来确定哪些路由不应应用 CSRF 过滤器。

对于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 过滤器。

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创建一个绑定!

【讨论】:

  • 这比 play 提出的创建超级机密 csrf 豁免 cookie 的建议要好得多
猜你喜欢
  • 1970-01-01
  • 2022-10-17
  • 2015-10-15
  • 2019-01-25
  • 2012-07-07
  • 2014-02-19
  • 1970-01-01
  • 2012-08-19
  • 2013-08-25
相关资源
最近更新 更多