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