有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java JAXRS AccessControlAllowOrigin头不存在,但已添加到ResponseFilter中

我正试图连接到使用JAX-RS构建的REST端点,但我得到的响应是,“Access Control Allow Origin”标题不存在。试图获得Angular2的资源

我尝试过的

我尝试了https://stackoverflow.com/a/30450944中提出的解决方案

我的回应过滤器:

@Provider
@PreMatching
public class ResponseFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        responseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
        responseContext.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
        responseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");
        responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }
}

还有我的网络。xml servlet映射:

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>com.api.ResponseFilter</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

更新1

更新了

responseContext.getHeaders().add(...);

responseContext.getHeaders.putSingle(...);

但我还是犯了同样的错误。 在postman中测试时,我得到了正确的标题:

Access-Control-Allow-Credentials →true
Access-Control-Allow-Headers →origin, content-type, accept, authorization
Access-Control-Allow-Methods →GET, POST, PUT, DELETE, OPTIONS, HEAD
Access-Control-Allow-Origin →*

更新2

在扩展应用程序的JAXRSConfig中,我手动添加了所有可能需要的资源:

@ApplicationPath("api")
public class JAXRSConfig extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new HashSet<>();
        addRestResourceClasses(resources);
        return resources;
    }

    private void addRestResourceClasses(Set<Class<?>> resources) {
        resources.add(AdminResource.class);
        resources.add(RequestFilter.class);
        resources.add(ResponseFilter.class);
        resources.add(TweetResource.class);
        resources.add(UserResource.class);
    }
}

通过使用断点,我注意到当我通过Postman发送get请求时,我的ResponseFilter确实会被调用,但当我通过我的应用程序发送get请求时,它不会被调用

发送请求的角度代码:

let headers = new Headers({'Authorization': authToken});
    headers.append('Content-Type', 'application/json');

    let options = new RequestOptions({ headers: headers});

    return this.http.get(http://localhost:8080/api/object/user)
      .map((res:Response) => res.json())
      .catch((error:any) => Observable.throw(error.json().error || 'Server error'));

更新3

我确实意识到我并没有将定义的头添加到请求中;所以我更新了我的角度代码:

let authToken = "Basic " + btoa("henk:asdf");//temporary until I learn how to allow a user to log in, in angular
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append('Authorization', authToken);

    //let options = new RequestOptions({ headers: headers});

    return this.http.get(this.myUrl, {headers: headers})
      .map((res:Response) => res.json())
      .catch((error:any) => Observable.throw(error.json().error || 'Server error'));

更新4

我后来了解到这可能是因为Chrome(和其他浏览器)通过名为OPTIONS的请求方法执行飞行前检查。我在api中添加了一个请求过滤器,如下所示:

@Provider
@PreMatching
public class RequestFilter implements ContainerRequestFilter {
    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        if (requestContext.getRequest().getMethod().equals("OPTIONS")) {
            requestContext.abortWith(Response.status(Response.Status.OK).header("Access-Control-Allow-Origin", "http://localhost:4200").build());
        }
    }
}

但没有用。在if语句中有一个断点,我看到这个方法不会在angular的get请求中被调用,但它会在Postman的请求中被调用

我还根据https://stackoverflow.com/a/19902666/6795661尝试了不同的CORS过滤器。 但这也不起作用

更新5

根据peeskillet,我尝试创建一个实现javax的类。servlet。过滤器,将所需的标题添加到响应中:

public class ContainerResponseFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.addHeader("Access-Control-Allow-Origin", "http://localhost:4200");
        res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        res.addHeader("Access-Control-Allow-Headers", "Content-Type");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}

在我的网站上有相应的映射。xml:

    <filter>
        <filter-name>corsfilter</filter-name>
        <filter-class>com.api.ContainerResponseFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>corsfilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

我在应用程序配置中添加了ContainerResponseFilter作为资源。 不幸的是,我仍然收到“访问控制允许来源”标题不存在的错误


共 (1) 个答案

  1. # 1 楼答案

    事实证明,问题在于身份验证。我的应用服务器试图对请求进行身份验证,但由于在进行身份验证之前进行了CORS检查,所以我得到了一个未经授权的响应,其中没有包含所需的头