Java 如何与异步Spring MVC控制器一起使用预授权
我有一个SpringMVC服务,可以让我上传一个文件。它使用Spring Security的@PreAuthorize来处理对资源的访问控制。控制器使用Servlet3异步Servlet,通过使用可调用的Java 如何与异步Spring MVC控制器一起使用预授权,java,spring,spring-mvc,spring-security,servlet-3.0,Java,Spring,Spring Mvc,Spring Security,Servlet 3.0,我有一个SpringMVC服务,可以让我上传一个文件。它使用Spring Security的@PreAuthorize来处理对资源的访问控制。控制器使用Servlet3异步Servlet,通过使用可调用的 @PreAuthorize("...") @RequestMapping(value = "upload", method = RequestMethod.PUT) public Callable<ResponseEntity> upload(final InputStream i
@PreAuthorize("...")
@RequestMapping(value = "upload", method = RequestMethod.PUT)
public Callable<ResponseEntity> upload(final InputStream inputStream)
{
return new Callable<ResponseEntity>()
{
@Override
public ResponseEntity call() throws Exception
{
...
}
};
}
异常似乎是由为我的Spring控制器生成的cglib代码引发的。这里是堆栈跟踪的大部分
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]
我已经根据SpringSecurity3.2中关于异步支持的说明更新了我的web.xml
最后,错误并不总是发生。只有当我试图上传一个大文件时才会出现这种情况。这让我认为,它确实与试图使控制器成为异步控制器有关
版本:
春季3.2.4
春季安全3.2
cglib 3.1
JavaServlet3.0
爪哇6
码头8
如果上载发生在派生线程中,则安全上下文可能不可用。这是因为默认情况下安全上下文绑定到父线程,而新的子线程不知道它 您可以尝试将SecurityContextHolder策略更改为InheritableThreadLocal,使其可用于生成的线程 您可以通过编程方式进行设置:
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL
或者在Spring XML配置中:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="org.springframework.security.core.context.SecurityContextHolder"/>
<property name="targetMethod" value="setStrategyName"/>
<property name="arguments"><list><value>MODE_INHERITABLETHREADLOCAL</value></list></property>
</bean>
如果上载发生在派生线程中,则安全上下文可能不可用。这是因为默认情况下安全上下文绑定到父线程,而新的子线程不知道它 您可以尝试将SecurityContextHolder策略更改为InheritableThreadLocal,使其可用于生成的线程 您可以通过编程方式进行设置:
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL
或者在Spring XML配置中:
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="org.springframework.security.core.context.SecurityContextHolder"/>
<property name="targetMethod" value="setStrategyName"/>
<property name="arguments"><list><value>MODE_INHERITABLETHREADLOCAL</value></list></property>
</bean>
不幸的是,这对我不起作用。我看到了同样的错误。您使用了设置策略的三种机制中的哪一种?我尝试了XML和编程方法。对于编程方法,我在构造函数中调用了SpringMVC控制器的构造函数。不幸的是,这对我不起作用。我看到了同样的错误。您使用了设置策略的三种机制中的哪一种?我尝试了XML和编程方法。对于编程方法,我在构造函数中调用SpringMVC控制器的构造函数。