0

I have a method that was annotated with @RolesAllowed from javax.annotation.security which is used by an existing aspect.

We are adding spring caching support to our service layer. The caching works just fine but we noticed that any @Cach* annotation on a method the existing aspect to not be hit.

Here is the method signature.

@Override
@RolesAllowed(Roles.VIEW_DATA)
@Cacheable(CacheConstants.DATATYPE_CACHENAME_PREFIX)
public List<Data> list(ListParams params)

Here is my CacheConfiguration. We are using spring boot 1.5.14 AutoConfig.

@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableConfigurationProperties
@EnableCaching
@SpringBootApplication
public class Application {

I have tried @EnableCaching with both proxyTargetClass = true and mode = aspectJ. Both did not work. mode = aspectJ caused the @RolesAllowed annotation to work again but then @Cacheable was being ignored.

This is the aspect that is no longer hit when @Cacheable is present.

@Aspect
@Component
public class ApplicationSecurityMethodInterceptor {

@Autowired
private MethodSecurityMetadataSource methodSecurityMetadataSource;

@Autowired
private  AccessDecisionManager methodAccessDecisionManager;

private static final Logger LOGGER = Logger.getLogger(ApplicationSecurityMethodInterceptor.class);

private static final String SCANNED_PACKAGE = "com.company.portal.service";
private static final String INTERCEPT_EXPRESSION = "within(" + SCANNED_PACKAGE + "..*)";



@Before(INTERCEPT_EXPRESSION)
public void intercept(JoinPoint joinPoint) {

    if (joinPoint == null) return;

    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    if (signature == null) return;

    Method method = signature.getMethod();
    if (method == null) return;

    Object target = joinPoint.getTarget();
    if (target == null) return;

    Class targetClass = joinPoint.getTarget().getClass();
    if (targetClass == null) return;

    Collection<ConfigAttribute> attributes = methodSecurityMetadataSource.getAttributes(method, targetClass);
    if (CollectionUtils.isEmpty(attributes)) return;

    LOGGER.debug(String.format("Intercepting method:[%s.%s], attributes:[%s]",
            targetClass.getName(), method.getName(), attributes));

    MethodInvocation mi = new SimpleMethodInvocation(target, method, joinPoint.getArgs());
    methodAccessDecisionManager.decide(SecurityContextHolder.getContext().getAuthentication(), mi, attributes);
}

}

  • Just to make sure I get this right, if you remove `@Cacheable` from that method above your aspect is invoked with no other change? – Stephane Nicoll Jul 13 '18 at 06:57
  • @StephaneNicoll so I have an update on this. It may be expected behavior after all. This was discovered during a test in which test data was inserted upstream which caused this method call to hit the cache. I checked the joinPoint, when Cacheable is there but nothing in cache, the joinPoint hits, but when the cache has the data, it does not hit the joinPoint as it does not even invoke the method. This poses a security problem for us that we have to address in our implementation. but not sure if this is a spring problem. – Justin ross Jul 13 '18 at 13:53
  • @StephaneNicoll this may be due to the ordering of my aspect and the custom spring aspect. I do not think i can fix that since I cannot control the ordering of the cache aspect, I can control the ordering of my aspect but it i set Order(HighestPrecedence) it causes all sorts of errors in order places in my application – Justin ross Jul 13 '18 at 13:55
  • If you have a minimal sample I can run myself, I am happy to have a look – Stephane Nicoll Jul 17 '18 at 06:49

0 Answers0