带有嵌入式Jetty的Cross Origin Filter

时间:2015-01-28 10:43:13

标签: jetty

我试图让CrossOriginFilter与几台嵌入式Jetty服务器一起工作,这两台服务器都运行在我们的内部网络上。两者都在运行servlet,但我需要服务器A的网页才能发布到服务器B的servlet。我想我需要将ACCESS_CONTROL_ALLOW_ORIGIN添加到CrossOriginFilter,但是找不到如何使用没有web.xml的嵌入式Jetty实例来证明这一点并不容易。尝试访问服务器b的serlvets

时,我在浏览器中收到以下错误消息
No 'Access-Control-Allow-Origin' header is present on the requested resource

我使用angularjs发布到控制器中的其他服务器的servlet。

这是其中一个服务器的代码(两者几乎相同)

Server server = new Server(httpPort);

ResourceHandler resource_handler = new ResourceHandler();
resource_handler.setDirectoriesListed(true);
resource_handler.setWelcomeFiles(new String[] { "index.html" });
resource_handler.setResourceBase("./http/");

ServletHandler handler = new ServletHandler();
handler.addServletWithMapping(ServerPageRoot.class, "/servlet/*");

FilterHolder holder = new FilterHolder(CrossOriginFilter.class);
holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
holder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,POST,HEAD");
holder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin");

handler.addFilter(holder );

HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] { resource_handler, handler,new DefaultHandler() });
server.setHandler(handlers);
server.start();

4 个答案:

答案 0 :(得分:9)

几点:

  • 不要那样赤裸地使用ServletHandlerServletHandlerServletContextHandler使用的内部类。
  • ServletContextHandler为您正在使用的各种servlet和过滤器提供所需的ServletContext对象和状态。
  • ServletContextHandler还为整个上下文路径声明提供了一个位置
  • ServletContextHandler也是欢迎文件声明的地方。
  • ResourceHandler可用时,请不要使用DefaultServlet,其功能更强大,功能更丰富。

示例:

Server server = new Server(httpPort);

// Setup the context for servlets
ServletContextHandler context = new ServletContextHandler();
// Set the context for all filters and servlets
// Required for the internal servlet & filter ServletContext to be sane
context.setContextPath("/");
// The servlet context is what holds the welcome list 
// (not the ResourceHandler or DefaultServlet)
context.setWelcomeFiles(new String[] { "index.html" });

// Add a servlet
context.addServlet(ServerPageRoot.class,"/servlet/*");

// Add the filter, and then use the provided FilterHolder to configure it
FilterHolder cors = context.addFilter(CrossOriginFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST));
cors.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
cors.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
cors.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,POST,HEAD");
cors.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin");

// Use a DefaultServlet to serve static files.
// Alternate Holder technique, prepare then add.
// DefaultServlet should be named 'default'
ServletHolder def = new ServletHolder("default", DefaultServlet.class);
def.setInitParameter("resourceBase","./http/");
def.setInitParameter("dirAllowed","false");
context.addServlet(def,"/");

// Create the server level handler list.
HandlerList handlers = new HandlerList();
// Make sure DefaultHandler is last (for error handling reasons)
handlers.setHandlers(new Handler[] { context, new DefaultHandler() });

server.setHandler(handlers);
server.start();

答案 1 :(得分:3)

设法通过

让它工作
FilterHolder holder = new FilterHolder(CrossOriginFilter.class);
holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
holder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,POST,HEAD");
holder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin");
holder.setName("cross-origin");
FilterMapping fm = new FilterMapping();
fm.setFilterName("cross-origin");
fm.setPathSpec("*");
handler.addFilter(holder, fm );

答案 2 :(得分:0)

我一直尝试以上答案和其他类似答案。但是总是,我遇到同样的错误信息。

最后,我对自己的情况给出了正确的答案。我将Jersey与Jetty一起使用,但未使用web.xml。如果尝试了所有方法,但未启用CORS支持,则可以在下面尝试此解决方案。

  1. 首先,定义一个过滤器(您可以定义另一个直接实现Filter类的过滤器)

import java.io.IOException;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.Response;

public class CorsFilter implements ContainerRequestFilter, ContainerResponseFilter {

    private static boolean isPreflightRequest(ContainerRequestContext request) {
        return request.getHeaderString("Origin") != null && request.getMethod().equalsIgnoreCase("OPTIONS");
    }

    @Override
    public void filter(ContainerRequestContext request) throws IOException {

        // If it's a preflight request, we abort the request 
        if (isPreflightRequest(request)) {
            request.abortWith(Response.ok().build());
            return;
        }
    }

    @Override
    public void filter(ContainerRequestContext request, ContainerResponseContext response) throws IOException {

        // if there is no Origin header, we don't do anything.
        if (request.getHeaderString("Origin") == null) {
            return;
        }

        // If it is a preflight request, then we add all
        // the CORS headers here.
        if (isPreflightRequest(request)) {
            response.getHeaders().add("Access-Control-Allow-Credentials", "true");
            response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
            response.getHeaders().add("Access-Control-Allow-Headers",
                    // Whatever other non-standard/safe headers (see list above)
                    // you want the client to be able to send to the server,
                    // put it in this list. And remove the ones you don't want.
                    "X-Requested-With,Content-Type,Content-Length,Authorization,"
                            + "Accept,Origin,Cache-Control,Accept-Encoding,Access-Control-Request-Headers,"
                            + "Access-Control-Request-Method,Referer,x-csrftoken,ClientKey");
        }

        response.getHeaders().add("Access-Control-Allow-Origin", "*");
    }
}
  1. 将此过滤器注册到资源配置

import java.io.IOException;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;

public class AppServer {

    public static void main(String[] args) throws Exception {

        Server jettyServer = new Server();

        // Add port
        ServerConnector jettyServerConnector = new ServerConnector(jettyServer);
        jettyServerConnector.setPort(Integer.parseInt("9090"));
        jettyServer.addConnector(jettyServerConnector);

        // Define main servlet context handler
        ServletContextHandler jettyServletContextHandler = new ServletContextHandler();
        jettyServletContextHandler.setContextPath("/service");

        // Define main resource (webapi package) support
        ResourceConfig webapiResourceConfig = new ResourceConfig();
        webapiResourceConfig.packages("com.example.service");
        ServletContainer webapiServletContainer = new ServletContainer(webapiResourceConfig);
        ServletHolder webapiServletHolder = new ServletHolder(webapiServletContainer);
        jettyServletContextHandler.addServlet(webapiServletHolder, "/webapi/*");

        // Add Cors Filter
        webapiResourceConfig.register(CorsFilter.class, 1);

        try {
            jettyServer.start();
            jettyServer.dump(System.err);
            jettyServer.join();
        } catch (Throwable t) {
            t.printStackTrace(System.err);
        } finally {
            jettyServer.destroy();
        }
    }
}

就是这样。此解决方案解决了我的问题。也许对其他人有用。

答案 3 :(得分:0)

即使这不是对原始问题的好答案,这也许会对某人有所帮助。我意识到,您可以通过直接在处理程序中操作标头来轻松地在嵌入式码头实例中启用跨源请求共享。下面的响应对象是HttpServletResponse的实例(传递给处理程序)。

示例:

response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Methods", "POST, GET");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");