I have a Spring MVC service which lets me upload a file. It uses @PreAuthorize
from Spring Security to handle access controls on resources. The controller uses Servlet 3 async servlets by use of a Callable.
@PreAuthorize("...")
@RequestMapping(value = "upload", method = RequestMethod.PUT)
public Callable<ResponseEntity> upload(final InputStream inputStream)
{
return new Callable<ResponseEntity>()
{
@Override
public ResponseEntity call() throws Exception
{
...
}
};
}
Somewhere in the service - outside of my code - an exception is being thrown.
An Authentication object was not found in the SecurityContext
The exception appears to be thrown by the cglib generated code for my Spring controller. Here is bulk of the stack trace.
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:339) ~[spring-security-core-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:198) ~[spring-security-core-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:60) ~[spring-security-core-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631) ~[spring-aop-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at com.testing.upload.controller.RESTService$$EnhancerByCGLIB$$66a0c4c9.upload(<generated>) ~[spring-core-3.2.4.RELEASE.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_65]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[na:1.6.0_65]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[na:1.6.0_65]
at java.lang.reflect.Method.invoke(Method.java:597) ~[na:1.6.0_65]
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219) ~[spring-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) ~[spring-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) ~[spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936) [spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:849) [spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:758) [javax.servlet-3.0.0.v201112011016.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) [spring-webmvc-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848) [javax.servlet-3.0.0.v201112011016.jar:na]
I have updated my web.xml from the instructions at the bottom of this blog post about async support in Spring Security 3.2.
Finally, the error does not always happen. It only appears to happen when I try to upload a large file. This makes me think that it does indeed have something to do with trying to make the controller an async controller.
Versions:
- Spring 3.2.4
- Spring Security 3.2
- cglib 3.1
- Java Servlet 3.0
- Java 6
- Jetty 8