3

Recently I started using SecurityEntityFilteringFeature. Placed below code in jersey environment.

environment.jersey().register(SecurityEntityFilteringFeature.class);
environment.jersey().register(JacksonFeature.class);

All my resource classes which are returning custom object or map, started throwing below exception

com.fasterxml.jackson.databind.JsonMappingException: Can not resolve PropertyFilter with id 'uk.co.froot.demo.openid.resources.PublicOAuthResource$1'; no FilterProvider configured
at com.fasterxml.jackson.databind.ser.std.StdSerializer.findPropertyFilter(StdSerializer.java:285)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:459)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:29)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:129)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:851)
at com.fasterxml.jackson.jaxrs.base.ProviderBase.writeTo(ProviderBase.java:648)
at org.glassfish.jersey.jackson.internal.FilteringJacksonJaxbJsonProvider.writeTo(FilteringJacksonJaxbJsonProvider.java:135)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:265)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:250)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:106)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:86)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1128)
at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:664)
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:421)
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:411)
Sam Berry
  • 7,394
  • 6
  • 40
  • 58
sanjay patel
  • 449
  • 8
  • 17
  • I have same problem. Click [here](http://stackoverflow.com/questions/35437298/jersey-jackson-data-entity-filtering-jsonmappingexception-on-collection) Another solution. – Sunshine Jiang Jan 26 '17 at 12:02

1 Answers1

3

Since no solution worked for me I had to create my own filter. Which usages Java security annotations. As per my custom requirement I had to set the Role for user in request. And that be used in filter

package com.buzzy.jersey.provider;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.annotation.security.DenyAll;
import javax.annotation.security.RolesAllowed;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;

import org.apache.commons.lang3.ClassUtils;

import uk.co.froot.demo.openid.model.security.Authority;

/**
 * @author Sanjay Patel (sanjaypatel at ibm.com)
 */
@Provider
public class FilterResponseFilter implements ContainerResponseFilter {

@Context
private ResourceInfo resourceInfo;
@Context
private HttpServletRequest request;

@Override
public void filter(ContainerRequestContext requestContext,
        ContainerResponseContext responseContext) throws IOException {
    if(responseContext.getEntity()!=null)
        filterObject(((Authority)request.getAttribute("hasAuthority")),responseContext.getEntity());
}

private void filterObject(Authority auth, Object entity) {
    if(entity instanceof List) {
        for(Object  obj: (List)entity)filterObject(auth,obj);
    }
    else if(entity instanceof Map) {
        for(Object obj : ((Map)entity).values()) filterObject(auth,obj);
    }
    else if(entity instanceof Object[]){
        for(Object  obj: (Object[])entity)filterObject(auth,obj);
    }
    else if(!ClassUtils.isPrimitiveOrWrapper(entity.getClass()) && !(entity instanceof String)){
        try{
            for(Method method:entity.getClass().getMethods()){
                if(method.getName().startsWith("get") && !method.getName().equals("getClass")){
                    String fieldName = method.getName().substring(3);
                    fieldName=fieldName.substring(0, 1).toLowerCase()+fieldName.substring(1, fieldName.length());
                    Field field = entity.getClass().getDeclaredField(fieldName);
                    field.setAccessible(true);
                    if(method.getAnnotation(DenyAll.class)!=null ){
                        field.set(entity, null);
                    }
                    if(method.getAnnotation(RolesAllowed.class)!=null){
                        if(auth!=null && Arrays.asList(method.getAnnotation(RolesAllowed.class).value()).contains(auth.name())){
                            if(!ClassUtils.isPrimitiveOrWrapper(method.getReturnType()) && !(entity instanceof String)){
                                filterObject(auth, field.get(entity));
                            }
                        }
                        else{
                            field.set(entity, null);
                        }
                    }
                }
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}
}

And register it dropwizard/jersey.

environment.jersey().register(FilterResponseFilter.class);
sanjay patel
  • 449
  • 8
  • 17
  • Thanks, Sanjay! This filter code helped me a lot for a similar problem. – albogdano Jul 13 '15 at 15:09
  • The above approach implements entity filtering manually, in a dirty manner, It does not resolve the problem "no FilterProvider configured", nor does it solve "disabling filter provider". Unfortunately I can confirm that after extensive attempts to get SecurityEntityFilteringFeature (works for simple cases) from Jersey 2.23 up and running. I got gridlocked in various problems and ended up implementing the feature manually too. – jediz Sep 15 '16 at 10:06
  • Awesome! I also failed to get SecurityEntityFilteringFeature working with DropWizard. This filter works like a champ. – Brandon Jan 12 '18 at 04:07