3

我一直在尝试将 Postman 与我的 Play Framework API 一起使用,但我一直遇到与 CSRF 过滤器相关的问题。

我浏览了一些论坛(包括 SO)以寻找解决此问题的方法,并且众所周知的建议似乎在添加:

play.filters.disabled+=play.filters.csrf.CSRFFilter

application.conf文件。

我已经尝试执行该修复,但即使我这样做了,我仍然在控制台日志中收到此错误:

[warn] p.filters.CSRF - [CSRF] Check failed because no token found in headers for /auth/logout

将cookie 设置为 JWT/auth/logout的 POST 请求在哪里。Authorization

我尝试了许多替代修复,例如设置play.filters.disabled[]or null,允许所有主机通过 CORS 过滤器,所有 3 的各种组合等,但最终相同的错误出现在我的日志中。

唯一对应用程序进行更改的是将 CSRF 令牌设置为 cookie 而不是在会话中,这会将错误更改为:

[warn] p.filters.CSRF - [CSRF] Check failed because none/none for /auth/logout

这让我至少知道application.conf正在正确加载,但它仍然不能解决问题。

是否有正确的方法来禁用我没有正确执行的 CSRF 过滤器?有没有另一种方法可以让 Postman 通过 CSRF 过滤器工作?

4

2 回答 2

3

好的,我发现了这个问题,但是挖掘问题的根源有点棘手。

当我将 macwire 添加到项目以进行依赖注入时,我必须定义一个自定义应用程序加载器,它需要一个自定义AppComponents类。我对AppComponents班级的声明如下所示:

class AppComponents(context: Context) extends BuiltInComponentsFromContext(context) with MyModule with AssetsComponents with I18nComponents with play.filters.HttpFiltersComponents

现在很明显,play.filters.HttpFiltersComponents具有以下字段:

def httpFilters: Seq[EssentialFilter] = Seq(csrfFilter, securityHeadersFilter, allowedHostsFilter)

其中csrfFiltersecurityHeadersFilterallowedHostsFilter是有效的硬编码值。我猜当使用 custom 时ApplicationLoader,它会忽略application.conf文件中设置的 http 过滤器(这在我写这篇文章时似乎很明显)。

我正在使用的当前解决方法/修复是设置val httpFilters: Seq[EssentialFilter] = Seq(securityHeadersFilter, allowedHostsFilter),而不是默认HttpFiltersComponents字段。我可能会稍微修改一下以从配置文件中读取过滤器,但现在这解决了问题。

TL;DR:在集成 MacWire 时添加了一个自定义 ApplicationLoader,没有意识到这会影响配置文件中的字段。

编辑

我使用 macwire 配置 HTTP 过滤器的最终代码ApplicationLoader如下所示,以防其他人需要它。它使用与 几乎完全相同的代码HttpFiltersComponents,但使用 macwire 而不是 Guice(未定义的变量继承自BuiltInComponentsFromContext):

override lazy val httpFilters: Seq[EssentialFilter] = {
    val wiredInstance: Wired = wiredInModule(this)
    val classes: Seq[Class[EssentialFilter]] = {
        val disabledFilters = config.get[Seq[String]]("play.filters.disabled")
        val enabledFilters = config.get[Seq[String]]("play.filters.enabled").filterNot(disabledFilters.contains)
        try {
            for (filterClassName <- enabledFilters) yield {
                try {
                    environment.classLoader.loadClass(filterClassName).asInstanceOf[Class[EssentialFilter]]
                } catch {
                    case e: ClassNotFoundException =>
                      throw configuration.reportError("play.filters.enabled", s"Cannot load class $filterClassName", Some(e))
                }
            }
        } catch {
            case e: ConfigException.Null =>
                Nil
            case e: ConfigException.Missing =>
                Nil
        }
    }
    classes.map(x => wiredInstance.wireClassInstance(x))
}
于 2017-11-02T18:09:00.053 回答
0

尝试在您的 application.conf 中添加以下代码:

play.filters.hosts {
  allowed = ["."]
}

让我知道它对你有用。检查官方播放文档

于 2017-11-02T16:44:25.893 回答