简体   繁体   English

嵌入式 Jetty 没有名为 cross-origin 的过滤器

[英]Embedded Jetty no filter named cross-origin

I am trying to implement cors in a embedded jetty server.我正在尝试在嵌入式码头服务器中实现 cors。 I feel lost right now with this exception.这个例外让我现在感到迷茫。

java.lang.IllegalStateException: No filter named cross-origin
    at org.eclipse.jetty.servlet.ServletHandler.updateMappings(ServletHandler.java:1260)
    at org.eclipse.jetty.servlet.ServletHandler.doStart(ServletHandler.java:179)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:171)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:89)
    at org.eclipse.jetty.server.handler.ScopedHandler.doStart(ScopedHandler.java:112)
    at org.eclipse.jetty.server.session.SessionHandler.doStart(SessionHandler.java:486)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:171)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:89)
    at org.eclipse.jetty.server.handler.ScopedHandler.doStart(ScopedHandler.java:112)
    at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:955)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:388)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:896)
    at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:306)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:171)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:121)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:89)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:171)
    at org.eclipse.jetty.server.Server.start(Server.java:469)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
    at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:89)
    at org.eclipse.jetty.server.Server.doStart(Server.java:414)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:93)
    at org.projectsanatan.restsanatan.RestSanatan.start(RestSanatan.java:38)
    at org.projectsanatan.restsanatan.Main.main(Main.java:16)

My code is我的代码是


    private void initServlets() {
        ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

        servletContextHandler.setContextPath("/");
        
        ResourceConfig resourceCfg = new ResourceConfig();
        resourceCfg.packages(BookResource.class.getPackage().getName(), "/*");
        
        ServletContainer servletContainer = new ServletContainer(resourceCfg);
        
        ServletHolder servletHolder = new ServletHolder(servletContainer);
        servletContextHandler.addServlet(servletHolder, "/api/*");
//        servletContextHandler.addFilter(null, KEY, null)
        
        FilterHolder corsFilter = new FilterHolder();
        corsFilter.setInitParameter("allowedOrigins", "https://example.com");
        corsFilter.setInitParameter("allowedMethods", "POST,GET,OPTIONS,PUT,DELETE,HEAD");
        corsFilter.setInitParameter("allowedHeaders", "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept");
        corsFilter.setInitParameter("preflightMaxAge", "728000");
        corsFilter.setInitParameter("allowCredentials", "true");
        corsFilter.setInitParameter("chainPreflight", "false");
        
        CrossOriginFilter cors = new CrossOriginFilter();
        
        corsFilter.setFilter(cors);
        
        FilterMapping corsFilterMap = new FilterMapping();
        corsFilterMap.setFilterName("cross-origin");
        corsFilterMap.setPathSpec("/*");
        corsFilterMap.setDispatcherTypes(EnumSet.of(DispatcherType.INCLUDE, DispatcherType.REQUEST));
        
        servletContextHandler.getServletHandler().addFilter(corsFilter, corsFilterMap);
        
        this.handlerList.addHandler(servletContextHandler);
        
        this.setHandler(this.handlerList);
    }

I am not very much experienced with jetty and servlet stuff so I am confused, help would be really appreciated!我对码头和 servlet 的东西不是很有经验,所以我很困惑,非常感谢帮助!

There's a few issues.有几个问题。

  1. Mapping of both Servlets and Filters is done by the ServletContextHandler , not the ServletHandler . Servlets 和过滤器的映射是由ServletContextHandler完成的,而不是ServletHandler
  2. If you use a FilterHolder + Mapping with name, then you have to name your FilterHolder .如果您使用带名称的FilterHolder + Mapping,则必须命名您的FilterHolder
    Mapping with name is overly complicated for embedded-jetty use, it really only exists for WEB-INF/web.xml based configuration.名称映射对于嵌入式码头使用来说过于复杂,它实际上只存在于基于WEB-INF/web.xml的配置中。 Just use the FilterHolder directly.直接使用FilterHolder即可。
  3. You are missing the required ServletContextHandler BaseResource declaration您缺少必需的ServletContextHandler BaseResource 声明
  4. You are missing the required DefaultServlet on your ServletContext您在ServletContext上缺少所需的DefaultServlet
  5. You are missing the DefaultHandler on your top level handler tree (usually set as last entry)您在顶级处理程序树上缺少DefaultHandler (通常设置为最后一个条目)

A correct setup would be like this...正确的设置应该是这样的……

ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
servletContextHandler.setContextPath("/");
// Base Resource is required for your setup
servletContextHandler.setBaseResource(Resource.newResource(urlToStaticContent));

ResourceConfig resourceCfg = new ResourceConfig();
resourceCfg.packages(BookResource.class.getPackage().getName(), "/*");

ServletContainer servletContainer = new ServletContainer(resourceCfg);

ServletHolder servletHolder = new ServletHolder(servletContainer);
servletContextHandler.addServlet(servletHolder, "/api/*");

FilterHolder corsHolder = servletContextHandler.addFilter(CrossOriginFilter.class,
    "/*",
    EnumSet.of(DispatcherType.INCLUDE, DispatcherType.REQUEST));

corsHolder.setInitParameter("allowedOrigins", "https://example.com");
corsHolder.setInitParameter("allowedMethods", "POST,GET,OPTIONS,PUT,DELETE,HEAD");
corsHolder.setInitParameter("allowedHeaders", "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept");
corsHolder.setInitParameter("preflightMaxAge", "728000");
corsHolder.setInitParameter("allowCredentials", "true");
corsHolder.setInitParameter("chainPreflight", "false");

// Default Servlet is Required
ServletHolder defaultHolder = new ServletHolder("default", DefaultServlet.class);
servletContextHandler.addServlet(defaultHolder, "/"); // default url-pattern

HandlerList handlerList = new HandlerList();
handlerList.addHandler(servletContextHandler);
// Default Handler is for requests that don't match a context above
// Such as requests that don't have a path that start with "/"
// It is safe to leave active, even in production, and will help with troubleshooting issues
handlerList.addHandler(new DefaultHandler());

server.setHandler(handlerList);

The Filter mapping of your CrossOriginFilter has specified the DispatcherType set of INCLUDE and REQUEST , that's a really odd setup.您的CrossOriginFilter的 Filter 映射指定了INCLUDEREQUESTDispatcherType集,这是一个非常奇怪的设置。

Doing CORS from an INCLUDE (or FORWARD ) dispatch is super awkward, skip it.INCLUDE (或FORWARD )调度执行 CORS 非常尴尬,跳过它。

But you didn't specify ASYNC , which is actually super common.但是您没有指定ASYNC ,这实际上非常常见。

I would change the mapping this way...我会这样改变映射......

FilterHolder corsHolder = servletContextHandler.addFilter(CrossOriginFilter.class,
    "/*",
    EnumSet.of(DispatcherType.REQUEST, DispatcherType.ASYNC));

Things to keep in mind for using CrossOriginFilter .使用CrossOriginFilter的注意事项。

  1. It will only produce HTTP Response headers based on your configuration.它只会根据您的配置生成 HTTP 响应标头。
  2. It does not "prevent" or "fail" any request that doesn't match your configuration.它不会“阻止”或“失败”任何与您的配置不匹配的请求。
  3. Requests without a Origin request header will not trigger the CrossOriginFilter .没有Origin请求 header 的请求不会触发CrossOriginFilter

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM