Play 2.3 override global SecurityHeadersFilter X-FRAME-OPTIONS 用于特定操作

Play 2.3 override global SecurityHeadersFilter X-FRAME-OPTIONS for a specific action

我在 Play 2.3 中全局启用了 SecurityHeadersFilter。

这是我的设置:

play.filters.headers.frameOptions="SAMEORIGIN"

但是我怎样才能用 X-Frame-Options=GOFORIT 而不是 SAMEORIGIN 覆盖一个动作?

使用动作组合。

首先,创建动作:

import play.libs.F.Promise;
import play.mvc.Action.Simple;
import play.mvc.Http.Context;
import play.mvc.Result;

public class XFrameOptionAction extends Simple {

    @Override
    public Promise<Result> call(Context ctx) throws Throwable {
        ctx.response().setHeader("X-Frame-Options", "GOFORIT");
        return delegate.call(ctx);
    }

}

然后,在你的控制器中使用它

import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.With;

public class MyController extends Controller {

    @With(XFrameOptionAction.class)
    public static Result index() {
        return ok();
    }

}

这将为 MyControllerindex 操作添加 header。 您还可以将注释放在控制器级别,以使控制器的所有操作都像这样。 如果你想让它对你的所有控制器通用,你需要创建一个你的所有控制器都将扩展的控制器。

这就是我用来避免 header 不被 SecurityHeadersFilter 覆盖的方法。

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

  val securityFilter = SecurityHeadersFilter()
  val defaultFilters = List(securityFilter)

  def filters(rh: RequestHeader) = {
    if (rh.path.startsWith("/cors_path")) 
      defaultFilters.filterNot(_.eq(securityFilter))
    else defaultFilters
  }
  override def doFilter(a: EssentialAction): EssentialAction = {
    FilterChainByRequestHeader(super.doFilter(a), filters)
  }