Java CORSFilter未应用于JAX-RS应用程序

Java CORSFilter未应用于JAX-RS应用程序,java,rest,jax-rs,wildfly,Java,Rest,Jax Rs,Wildfly,我使用的是resteasyjaxrs-3.0.9.FINAL。 我有两个独立的javax.ws.rs.core.Applications @ApplicationPath("oauth") public class OAuthApplication extends Application { final Set<Class<?>> classes = new HashSet<>(); @Nonnull @Override pu

我使用的是
resteasyjaxrs-3.0.9.FINAL
。 我有两个独立的
javax.ws.rs.core.Application
s

@ApplicationPath("oauth")
public class OAuthApplication extends Application {
    final Set<Class<?>> classes = new HashSet<>();

    @Nonnull
    @Override
    public Set<Class<?>> getClasses() {
        classes.add(RegisterResource.class);
        classes.add(TokenResource.class);
        classes.add(HelloResource.class);
        return Collections.unmodifiableSet(classes);
    }
}
我的过滤器看起来像

@Provider
public class CorsFeature implements Feature {

  @Override
  public boolean configure(FeatureContext featureContext) {
    CorsFilter corsFilter = new CorsFilter();
    corsFilter.getAllowedOrigins().add("*");
    corsFilter.setAllowedMethods("OPTIONS, GET, POST, DELETE, PUT, PATCH");
    featureContext.register(corsFilter);
    return true;
  }
}
我还对我的
/rest/*
资源应用过滤器,如下所示

@WebFilter("/rest/*")
public class AuthTokenValidatorFilter implements Filter {
    private static final String BEARER_HEADER = "BEARER";
    private static final String COLON = ":";
    private static final Pattern PATTERN = Pattern.compile(COLON);

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

    @Override
    public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
        final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        final HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;

        if (httpRequest.getHeader(BEARER_HEADER) == null || !isValidAuthToken(httpRequest.getHeader(BEARER_HEADER))) {
            httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    private static boolean isValidAuthToken(@Nonnull final String header) {
        final String[] tokenParts = PATTERN.split(header);
        if (tokenParts.length != 3) {
            // hash, uuid, timestamp
            return false;
        }

        final int nanoTimeStamp;
        try {
            nanoTimeStamp = Integer.parseInt(tokenParts[2]);
        } catch (final NumberFormatException e) {
            return false;
        }

        final String hashedAuthToken = new UniqueIdGenerator().getHashedAuthToken(tokenParts[1], nanoTimeStamp);
        return hashedAuthToken.equals(tokenParts[0]);
    }

    @Override
    public void destroy() {
    }
}
当我启动应用程序并到达端点时,我看到

 ~ curl -v http://localhost:9090/application/oauth/hello
*   Trying ::1...
* Connected to localhost (::1) port 9090 (#0)
> GET /application/oauth/hello HTTP/1.1
> Host: localhost:9090
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Connection: keep-alive
< X-Powered-By: Undertow 1
< Server: Wildfly 8
< Content-Type: application/octet-stream
< Content-Length: 5
< Date: Fri, 26 May 2017 19:05:15 GMT
<
* Connection #0 to host localhost left intact
hello%
~curl-vhttp://localhost:9090/application/oauth/hello
*正在尝试::1。。。
*已连接到本地主机(::1)端口9090(#0)
>GET/application/oauth/hello HTTP/1.1
>主机:localhost:9090
>用户代理:curl/7.43.0
>接受:*/*
>
我没有看到CORS头被发回。
我在这里遗漏了什么?

您是否调试并检查请求是否通过过滤器?我不确定将其作为一个功能实现是否有效,但从我所能找到的情况来看,大多数资源建议实现CORS过滤器,如下所示

@Provider
public class CorsFilter 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-Credentials", "true");
      responseContext.getHeaders().add("Access-Control-Allow-Headers","origin, content-type, accept, authorization");
      responseContext.getHeaders().add("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }
}
参考资料:


我猜您的代码来自。这个问答的要点是OP希望能够继续使用类路径扫描,即保持

@ApplicationPath("/api")
public class RestApplication extends Application {
}
当您有这样一个空的
应用程序
类时,它会触发用
@Path
@Provider
注释的类的类路径扫描。所有这些类都会自动注册。但是,一旦在
应用程序
类中重写
getClasses()
getSingletons()
,并在其中任何一个中返回非空集,类路径扫描将自动禁用

因此OP试图找出如何在不禁用类路径扫描的情况下注册
CorsFilter
。解决方案是使用带有
@Provider
注释的
功能。
@Provider
允许自动查找和注册
功能

在您的例子中,由于禁用了类路径扫描,所以没有进行类路径扫描。因此,您只需要注册
功能
,或者因为您没有使用类路径扫描,您可以忘记
功能
,直接在
应用程序
类中注册
CorsFilter

@Override
public Set<Object> getSingletons() {
    Set<Object> providers = new HashSet<>();
    CorsFilter corsFilter = new CorsFilter();
    corsFilter.getAllowedOrigins().add("*");
    corsFilter.setAllowedMethods("OPTIONS, GET, POST, DELETE, PUT, PATCH");
    providers.add(corsFilter);
    return providers;
}

是的,我试过了,但即使在这种情况下,调用也没有通过
ContainerResponseFilter
。伙计,你救了我的命,如果你想的话,你应该为3.1.x resteasy更新对它的引用,因为我看到的所有其他3.0.9实现在此之后都崩溃了。
@Override
public Set<Object> getSingletons() {
    Set<Object> providers = new HashSet<>();
    CorsFilter corsFilter = new CorsFilter();
    corsFilter.getAllowedOrigins().add("*");
    corsFilter.setAllowedMethods("OPTIONS, GET, POST, DELETE, PUT, PATCH");
    providers.add(corsFilter);
    return providers;
}
if (notAuthenticated()) {
    requestContext.abortWith(Response.status(401).build()));
    return;
}