31

我正在使用本教程中描述的身份验证/授权机制构建休息服务:http: //howtodoinjava.com/2013/06/26/jax-rs-resteasy-basic-authentication-and-authorization-tutorial/

基本上,它使用PreProcessInterceptor接口扫描目标方法的注释(来自javax.annotation.security包),这些注释描述了访问该方法所需的角色。由于这里的authenticator是一个拦截器,它可以取消目标方法调用,如果需要返回一个401(未授权)。

这里的问题是接口 org.jboss.resteasy.spi.interception.PreProcessInterceptor 在当前的 RestEasy 版本(3.0.1)中已被弃用,我在尝试使用标准 JAX-RS 接口实现相同的行为时遇到问题.

我正在使用 javax.ws.rs.ext.ReaderInterceptor 接口来拦截调用。但不知何故,服务器从不调用它:拦截器只是被忽略了。

我注册拦截器/资源的方式与之前的 PreProcessInterceptor 相同,并使用相同的 @Provider 和 @ServerInterceptor 注释:

服务器应用程序:

public class ServerApplication extends javax.ws.rs.core.Application {

     private final HashSet<Object> singletons = new LinkedHashSet<Object>();

     public ServerApplication() {
         singletons.add(new SecurityInterceptor());
         singletons.add( ... ); //add each of my rest resources
     }

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

    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }
}

安全拦截器:

@Provider
@ServerInterceptor
public class SecurityInterceptor implements javax.ws.rs.ext.ReaderInterceptor {
     @Override
     public Object aroundReadFrom(ReaderInterceptorContext context){
            //code that is never called... so lonely here...
     }
}

关于如何解决这个问题的任何见解?

谢谢你。

4

3 回答 3

29

RESTEasy 3.xx 符合 JAX-RS 2.0 规范。

您正在尝试做的事情可以通过以下方式完成(也许更好):

@Provider
public class SecurityInterceptor 
      implements javax.ws.rs.container.ContainerRequestFilter {
     @Override
     public void filter(ContainerRequestContext requestContext){
       if (not_authenticated){ requestContext.abortWith(response)};
     }
}

因为ReaderInterceptor仅当底层MessageBodyReader.readFrom由标准 JAX-RS 管道调用时才会调用,而不是从应用程序代码调用。

但是,没有调用您的拦截器的原因可能是 @ServerInterceptor注释,它是一个 RESTEasy 扩展。

规范在 §6.5.2 中指出,拦截器是全局注册的,除非使用@Provider注释进行@NameBinding注释,但我不知道是否RESTEasy可以处理@ServerInterceptor如果它没有显式注册,如RestEASY Interceptor Not Being Called中所示

于 2013-07-11T15:41:18.520 回答
4

如果您需要访问底层java.lang.reflect.Method(就像您过去能够通过实施获得AcceptedByMethod),您可以执行以下操作:

ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) 
            requestContext.getProperty("org.jboss.resteasy.core.ResourceMethodInvoker");
Method method = methodInvoker.getMethod();
于 2013-11-26T16:54:15.360 回答
3

我还想访问底层java.lang.reflect.Method并尝试使用 Resteasy 3.0.8 提供 mtpettyp 的答案,但在 getProperty 调用中返回 null。我也在使用 Spring 和 resteasy-spring,尽管我认为这根本不会影响这一点。

如果您遇到我的情况并正在实现 Post Matching ContainerRequestFilter(如果您希望获得匹配的资源方法,则必须这样做),那么您实际上可以将其ContainerRequestContext转换为 Resteasy 为 Post Match 场景提供的实现。PostMatchContainerRequestContext具有对 ResourceMethodInvoker 的引用。

public void filter(ContainerRequestContext context) throws IOException {
    PostMatchContainerRequestContext pmContext = (PostMatchContainerRequestContext) context;

    Method method = pmContext.getResourceMethod().getMethod();

    /* rest of code here */
}
于 2014-05-16T16:30:10.223 回答