Java 如何从其他来源访问url?即使存在Access Control Allow-*标头,飞行前请求也会返回401

Java 如何从其他来源访问url?即使存在Access Control Allow-*标头,飞行前请求也会返回401,java,cors,jetty,embedded-jetty,Java,Cors,Jetty,Embedded Jetty,我在嵌入式jetty中使用基本身份验证运行simple Jersey REST端点,并尝试通过来自其他web应用程序的ajax调用访问它。但我得到401未经授权的飞行前请求,即使访问控制允许-*头存在 服务器代码: public final class RESTServerStarter { private static final int WEB_SERVER_PORT = 8888; public static void main(String[] args) throws Excepti

我在嵌入式jetty中使用基本身份验证运行simple Jersey REST端点,并尝试通过来自其他web应用程序的ajax调用访问它。但我得到401未经授权的飞行前请求,即使访问控制允许-*头存在

服务器代码:

public final class RESTServerStarter {
private static final int WEB_SERVER_PORT = 8888;

public static void main(String[] args) throws Exception {
    final ServletHolder sh = new ServletHolder(ServletContainer.class);
    sh.setInitParameter(ServletContainer.RESOURCE_CONFIG_CLASS, PackagesResourceConfig.class.getCanonicalName());
    sh.setInitParameter(PackagesResourceConfig.PROPERTY_PACKAGES, HelloRESTService.class.getPackage().getName());

    final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setSecurityHandler(basicAuth("admin", "adminpwd", "Private!"));
    context.setContextPath("/rest");
    context.addServlet(sh, "/*");
    context.addFilter(MyFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));

    final Server server = new Server();

    final ServerConnector connector = new ServerConnector(server);
    connector.setHost("172.18.133.20");
    connector.setPort(WEB_SERVER_PORT);
    server.addConnector(connector);

    server.setHandler(context);

    try {
        server.start();
        server.join();
    } finally {
        server.destroy();
    }

}

private static final SecurityHandler basicAuth(String username, String password, String realm) {

    HashLoginService hashLoginService = new HashLoginService();
    hashLoginService.putUser(username, Credential.getCredential(password), new String[]{"user"});
    hashLoginService.setName(realm);

    Constraint constraint = new Constraint();
    constraint.setName(Constraint.__BASIC_AUTH);
    constraint.setRoles(new String[]{"user"});
    constraint.setAuthenticate(true);

    ConstraintMapping cm = new ConstraintMapping();
    cm.setConstraint(constraint);
    cm.setPathSpec("/*");

    ConstraintSecurityHandler csh = new ConstraintSecurityHandler();
    csh.setAuthenticator(new BasicAuthenticator());
    csh.setRealmName("myrealm");
    csh.addConstraintMapping(cm);
    csh.setLoginService(hashLoginService);

    return csh;

}

public static final class MyFilter implements Filter {
    public void init(FilterConfig filterConfig) {
        //nothing to init
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        final HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.addHeader("Access-Control-Allow-Origin", "http://172.18.133.20:" + RESTClientStarter.WEB_SERVER_PORT);
        httpResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE, PUT");
        httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.addHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
        chain.doFilter(request, response);
    }

    public void destroy() {
        //nothing to destroy
    }
}

@Path("/test")
public static class HelloRESTService {

    @GET
    @Path("hello")
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }
}
}

客户端代码:

$(function(){
    $.ajax({
        url : "http://172.18.133.20:8888/rest/test/hello",
        type : "GET",
        timeout : 120000,
        async : true,
        xhrFields: {
            withCredentials: true
        },
        crossDomain: true,
        headers: {
            "Authorization": "Basic " + btoa("admin:adminpwd")
        },
        error: function(xhr, status, error) {
            $("#container").text(error);
        },
        success: function(xhr) {
            $("#container").text(xhr);
        }
    });
});
客户端代码在上运行

以下是全部资料来源:

你能告诉我怎么了吗


谢谢你的进步

我认为您应该使用httpResponse.addHeader(“访问控制允许源代码”,:“+RESTClientStarter.WEB\u服务器\u端口”); rest应用程序的WEB_服务器_端口是9999,所以httpResponse允许。
但是您在8888端口调用它,这是不允许的。

我认为您使用的是httpResponse.addHeader(“访问控制允许源代码”,:“+RESTClientStarter.WEB\u服务器\u端口); rest应用程序的WEB_服务器_端口是9999,所以httpResponse允许。
但是您在8888端口调用它,这是不允许的。

我已经解决了排除SecurityMapping的选项请求的问题。只需添加一行:

...
ConstraintMapping cm = new ConstraintMapping();
cm.setMethod("GET"); //new line
cm.setConstraint(constraint);
cm.setPathSpec("/*");
...

我已经解决了从SecurityMapping排除选项请求的问题。只需添加一行:

...
ConstraintMapping cm = new ConstraintMapping();
cm.setMethod("GET"); //new line
cm.setConstraint(constraint);
cm.setPathSpec("/*");
...

否。REST应用程序在8888端口上运行,客户端应用程序在9999端口上运行。因此,您应该尝试httpResponse.addHeader(“访问控制允许源代码”);而不是httpResponse.addHeader(“访问控制允许源代码”),:“+RESTClientStarter.WEB_服务器_端口);为什么?ajax reuest的起源是。我试过你的决定,但它不起作用。因为如果你写172.18.133.20,你的服务器是allow all request from this ip,或者你可以写*for allow all request from any ip/域。你应该将X-PINGOTHER添加到Access Control allow Header中,因为服务器应该是allow all method,它可以运行。No.REST应用程序在8888端口上运行,客户端应用程序在9999端口上运行,因此,您应该尝试httpResponse.addHeader(“访问控制允许源代码”);而不是httpResponse.addHeader(“访问控制允许源代码“,”:“+RESTClientStarter.WEB\u服务器\u端口);为什么?ajax reuest的起源是。我已经尝试过你的决定,但它不起作用。因为如果你写172.18.133.20,你的服务器将允许来自此ip的所有请求,或者你可以写*以允许来自任何ip/域的所有请求。您应该将X-PINGOTHER添加到Access Control Allow头中,因为服务器应该是Allow all方法,它可以运行。