嵌入式码头CrossDomainFilter不工作

Posted

技术标签:

【中文标题】嵌入式码头CrossDomainFilter不工作【英文标题】:embedded jetty CrossDomainFilter not working 【发布时间】:2015-07-11 03:12:03 【问题描述】:

我找不到使用我的处理程序和过滤器组合的嵌入式码头的示例。由于某种原因,我无法确定我没有得到 CORS 标头。这是我目前的来源:

private static Server setupJetty(Properties prop) 
    Server server = new Server(Integer.parseInt(prop.getProperty("port")));
    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath(prop.getProperty("contextpath"));
    ContextHandlerCollection contexts = new ContextHandlerCollection();
    RequestLogHandler requestLogHandler= setupLogging(server, prop.getProperty("logslocn"));
    ServletHolder jerseyServlet = context.addServlet(ServletContainer.class, "/*");
    jerseyServlet.setInitOrder(0);

    // Tells the Jersey Servlet which REST service/class to load.
    jerseyServlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES, "org.example.pss.resources");
    context.addServlet(jerseyServlet, prop.getProperty("servletpath"));

    ServletHandler handler = new ServletHandler();
    handler.addServletWithMapping(jerseyServlet, "/*");

    FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
    filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");    // allowed origins comma separated
    filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin");
    filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,PUT,POST,DELETE,OPTIONS");
    filterHolder.setInitParameter(CrossOriginFilter.PREFLIGHT_MAX_AGE_PARAM, "5184000"); // 2 months
    filterHolder.setInitParameter(CrossOriginFilter.ALLOW_CREDENTIALS_PARAM, "true");
    filterHolder.setName("cross-origin");
    FilterMapping fm = new FilterMapping();
    fm.setFilterName("cross-origin");
    fm.setPathSpec("*");       
    handler.addFilter(filterHolder,fm);

    HandlerCollection handlers = new HandlerCollection();
    handlers.setHandlers(new Handler[]context, handler, contexts, 
            new DefaultHandler(), requestLogHandler);
    server.setHandler(handlers);
    return server;

我也试过了:

    FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
    filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "/*");    // allowed origins comma separated
    filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin");
    filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,PUT,POST,DELETE,OPTIONS");
    filterHolder.setInitParameter(CrossOriginFilter.PREFLIGHT_MAX_AGE_PARAM, "5184000"); // 2 months
    filterHolder.setInitParameter(CrossOriginFilter.ALLOW_CREDENTIALS_PARAM, "true");
    context.addFilter(filterHolder,"/*",EnumSet.allOf(DispatcherType.class));

    HandlerCollection handlers = new HandlerCollection();
    handlers.setHandlers(new Handler[]context, contexts, 
            new DefaultHandler(), requestLogHandler);
    server.setHandler(handlers);

同样的结果,我从来没有看到跨域标头。我还需要做什么才能使此过滤器正常工作?

【问题讨论】:

【参考方案1】:

不要直接使用ServletHandler,那是一个内部类。 过滤器始终是ServletContextHandler(或更专业的WebAppContext)的一部分

您的配置在 /* 上下文路径中添加了 2 个 servlet(这是不行的)

您的配置在DefaultHandler 之后添加您的RequestLogHandler(这意味着RequestLogHandler 永远不会运行)

DefaultHandler 应该在主处理程序列表的末尾

DefaultServlet 需要存在于您的ServletContextHandler

您的ServletContextHandler 缺少必需的resourceBase(这是指向有效位置的路径或URL,以使ServletContext 可以正常查找资源)

* 的路径规范无效。 (请记住,您可以使用前缀/a/b/*、后缀*.foo、精确/a/b/c 或默认/

所以,为了简化...

package org.eclipse.jetty.demo;

import java.util.EnumSet;

import javax.servlet.DispatcherType;

import org.eclipse.jetty.server.AsyncNCSARequestLog;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.servlet.ServletContainer;

public class JerseyWithCors

    public static void main(String[] args)
    
        try
        
            new JerseyWithCors().exec();
        
        catch (Throwable t)
        
            t.printStackTrace(System.err);
        
    

    public void exec() throws Exception
    
        int port = 8080;
        Server server = new Server(port);
        HandlerList handlers = new HandlerList();
        server.setHandler(handlers);

        handlers.addHandler(getAccessLogHandler());
        handlers.addHandler(getMainServletContext());

        // DefaultHandler is always last for the main handler tree
        // It's responsible for Error handling of all prior handlers.
        // It will always respond (if the request reaches this far)
        handlers.addHandler(new DefaultHandler());

        server.start();
        server.join();
    

    public Handler getAccessLogHandler()
    
        RequestLogHandler logHandler = new RequestLogHandler();
        AsyncNCSARequestLog log = new AsyncNCSARequestLog();
        log.setFilename("logs/access-yyyy_mm_dd.log");
        logHandler.setRequestLog(log);
        return logHandler;
    

    public Handler getMainServletContext()
    
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        // always need a resource base
        context.setResourceBase("path/to/webroot");

        ServletHolder jerseyServlet = context.addServlet(ServletContainer.class,"/*");
        jerseyServlet.setInitOrder(0);
        jerseyServlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES,"org.example.pss.resources");

        FilterHolder filterHolder = context.addFilter(CrossOriginFilter.class,"/*",EnumSet.allOf(DispatcherType.class));
        filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM,"*");
        filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM,"Content-Type,Authorization,X-Requested-With,Content-Length,Accept,Origin");
        filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM,"GET,PUT,POST,DELETE,OPTIONS");
        filterHolder.setInitParameter(CrossOriginFilter.PREFLIGHT_MAX_AGE_PARAM,"5184000");
        filterHolder.setInitParameter(CrossOriginFilter.ALLOW_CREDENTIALS_PARAM,"true");

        // DefaultServlet is always last for a ServletContext
        context.addServlet(DefaultServlet.class,"/");

        return context;
    

【讨论】:

谢谢乔金。像这样的示例将增强 Jetty 的文档,嵌入式设置没有涵盖 webapp 操作和静态配置文件。 我仍然没有得到 CORS 标头?我添加了: filterHolder.setInitParameter(CrossOriginFilter.EXPOSED_HEADERS_PARAM,("Access-Control-Allow-Origin"));还是不明白。所以目前还没有跨域支持。我怎么得到这个?我 GET 带有标题:主机:pss.hcl.com:8088 用户代理:Mozilla/5.0 (Windows NT 6.3; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0 接受:text/html,application/xhtml+xml, application/xml;q=0.9,/;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Get:

以上是关于嵌入式码头CrossDomainFilter不工作的主要内容,如果未能解决你的问题,请参考以下文章

嵌入式码头热部署

如何使用嵌入式码头添加 servlet 过滤器

为啥有人会使用 jetty-maven-plugin 与嵌入式码头

如何让 WebApp 在嵌入式码头的类路径上找到应用程序属性?

markdown havre /像这样的码头工人运行嵌入式squashfs图像

嵌入式码头服务器的 Spring Boot 数据源特定属性