尽管定义了 RequestContextListener,但创建名称为 'scopedTarget.oauth2ClientContext' 的 bean 时出错
Error creating bean with name 'scopedTarget.oauth2ClientContext' despite defining RequestContextListener
我的应用有多个 spring 安全配置,其中之一恰好是 Oauth2
(使用 this eaxmple)。
Spring 总体安全性通过以下方式插入:
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.addFilter(GzipFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
context.addFilter(new FilterHolder( new DelegatingFilterProxy( DEFAULT_FILTER_NAME ) ), "/*",EnumSet.allOf( DispatcherType.class ));
AnnotationConfigWebApplicationContext securityContext = new AnnotationConfigWebApplicationContext();
securityContext.setConfigLocation("com.test.auth");
DispatcherServlet dispatcherServlet = new DispatcherServlet(securityContext);
context.addServlet(new ServletHolder(dispatcherServlet), "/");
context.addServlet(new ServletHolder(new ServletContainer(createResourceConfig(AuthController.class))), "/auth/*");
Oauth2 看起来像这样:
@Order(4)
@EnableOAuth2Client
@EnableWebSecurity
@Configuration
public class Oauth2Config extends WebSecurityConfigurerAdapter {
@Bean
@Order(0)
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
@Autowired
private OAuth2ClientContext oauth2ClientContext;
@Autowired
private OAuth2ClientContextFilter oauth2ClientContextFilter;
@Autowired
private AuthConfig authConfig;
private OAuth2ProtectedResourceDetails authorizationCodeResource() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId("google-oauth-client");
details.setClientId(authConfig.getProperty("oauth2.clientId"));
details.setClientSecret(authConfig.getProperty("oauth2.clientSecret"));
details.setUserAuthorizationUri(authConfig.getProperty("oauth2.userAuthorizationUri"));
details.setAccessTokenUri(authConfig.getProperty("oauth2.accessTokenUri"));
details.setTokenName(authConfig.getProperty("oauth2.tokenName"));
details.setScope(Arrays.asList(authConfig.getPropertyList("oauth2.scope")));
details.setAuthenticationScheme(AuthenticationScheme.query);
details.setClientAuthenticationScheme(AuthenticationScheme.form);
return details;
}
@Bean
public OAuth2ClientAuthenticationProcessingFilter
oauth2ClientAuthenticationProcessingFilter() {
// Used to obtain access token from authorization server (AS)
OAuth2RestOperations restTemplate = new OAuth2RestTemplate(
authorizationCodeResource(),
oauth2ClientContext);
OAuth2ClientAuthenticationProcessingFilter filter =
new OAuth2ClientAuthenticationProcessingFilter(authConfig.getProperty("oauth2.filterCallbackPath"));
filter.setRestTemplate(restTemplate);
// Set a service that validates an OAuth2 access token
// We can use either Google API's UserInfo or TokenInfo
// For this, we chose to use UserInfo service
filter.setTokenServices(googleUserInfoTokenServices());
return filter;
}
@Bean
public GoogleUserInfoTokenServices googleUserInfoTokenServices() {
GoogleUserInfoTokenServices userInfoTokenServices =
new GoogleUserInfoTokenServices(authConfig.getProperty("oauth2.userInfoUri"), authConfig.getProperty("oauth2.clientId"));
// TODO Configure bean to use local database to read authorities
// userInfoTokenServices.setAuthoritiesExtractor(authoritiesExtractor);
return userInfoTokenServices;
}
@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
// May need an OAuth2AuthenticationEntryPoint for non-browser clients
return new LoginUrlAuthenticationEntryPoint(authConfig.getProperty("oauth2.filterCallbackPath"));
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/", "/static/**", "/webjars/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint());
http
.antMatcher("/auth/oauth/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.addFilterAfter(
oauth2ClientContextFilter,
ExceptionTranslationFilter.class)
.addFilterBefore(
oauth2ClientAuthenticationProcessingFilter(),
FilterSecurityInterceptor.class)
.anonymous()
.disable();
}
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return new NoopAuthenticationManager();
}
}
private static class NoopAuthenticationManager implements AuthenticationManager {
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
throw new UnsupportedOperationException(
"No authentication should be done with this AuthenticationManager");
}
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
访问回调 url api/auth/oauth/callback
时,出现以下异常:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'scopedTarget.oauth2ClientContext': Scope
'session' is not active for the current thread; consider defining a
scoped proxy for this bean if you intend to refer to it from a
singleton
在搜索 SO 时,建议的解决方案是添加 RequestContextListener
bean,但即使添加之后我也没有成功。
一个 solution 也建议使用 FilterRegistrationBean
但我没有使用 Springboot 所以我不确定它是否能解决我的问题。
完整异常跟踪:
2018-02-22 12:47:36,440 - /api/auth/oauth/callback
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'scopedTarget.oauth2ClientContext': Scope
'session' is not active for the current thread; consider defining a
scoped proxy for this bean if you intend to refer to it from a
singleton; nested exception is java.lang.IllegalStateException: No
thread-bound request found: Are you referring to request attributes
outside of an actual web request, or processing a request outside of
the originally receiving thread? If you are actually operating within
a web request and still receive this message, your code is probably
running outside of DispatcherServlet/DispatcherPortlet: In this case,
use RequestContextListener or RequestContextFilter to expose the
current request. at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:355)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at
org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192)
at com.sun.proxy.$Proxy64.getAccessToken(Unknown Source) at
org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:169)
at
org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:105)
at
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:60)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
at
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347)
at
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263)
at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at
org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:83)
at
org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:364)
at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
at
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221)
at
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
at
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
at
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215)
at
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:497) at
org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310) at
org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
at
org.eclipse.jetty.io.AbstractConnection.run(AbstractConnection.java:540)
at
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at
org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Unknown Source) Caused by:
java.lang.IllegalStateException: No thread-bound request found: Are
you referring to request attributes outside of an actual web request,
or processing a request outside of the originally receiving thread? If
you are actually operating within a web request and still receive this
message, your code is probably running outside of
DispatcherServlet/DispatcherPortlet: In this case, use
RequestContextListener or RequestContextFilter to expose the current
request. at
org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at
org.springframework.web.context.request.SessionScope.get(SessionScope.java:91)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340)
... 55 more
我解决了这个问题。而且在这个Springboot
的时代,用稍微老一点的系统的人可能会觉得答案有用,所以分享一下。
RequestContextListener
需要像这样在码头配置中添加:
context.addEventListener(new RequestContextListener());
我将它添加到我的安全配置文件中,如下所示:
@Bean
@Order(0)
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
有人会觉得这很有用,在 AbstractAnnotationConfigDispatcherServletInitializer 实现中添加以下内容 class:
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addListener(new RequestContextListener());
}
我的应用有多个 spring 安全配置,其中之一恰好是 Oauth2
(使用 this eaxmple)。
Spring 总体安全性通过以下方式插入:
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.addFilter(GzipFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
context.addFilter(new FilterHolder( new DelegatingFilterProxy( DEFAULT_FILTER_NAME ) ), "/*",EnumSet.allOf( DispatcherType.class ));
AnnotationConfigWebApplicationContext securityContext = new AnnotationConfigWebApplicationContext();
securityContext.setConfigLocation("com.test.auth");
DispatcherServlet dispatcherServlet = new DispatcherServlet(securityContext);
context.addServlet(new ServletHolder(dispatcherServlet), "/");
context.addServlet(new ServletHolder(new ServletContainer(createResourceConfig(AuthController.class))), "/auth/*");
Oauth2 看起来像这样:
@Order(4)
@EnableOAuth2Client
@EnableWebSecurity
@Configuration
public class Oauth2Config extends WebSecurityConfigurerAdapter {
@Bean
@Order(0)
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
@Autowired
private OAuth2ClientContext oauth2ClientContext;
@Autowired
private OAuth2ClientContextFilter oauth2ClientContextFilter;
@Autowired
private AuthConfig authConfig;
private OAuth2ProtectedResourceDetails authorizationCodeResource() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId("google-oauth-client");
details.setClientId(authConfig.getProperty("oauth2.clientId"));
details.setClientSecret(authConfig.getProperty("oauth2.clientSecret"));
details.setUserAuthorizationUri(authConfig.getProperty("oauth2.userAuthorizationUri"));
details.setAccessTokenUri(authConfig.getProperty("oauth2.accessTokenUri"));
details.setTokenName(authConfig.getProperty("oauth2.tokenName"));
details.setScope(Arrays.asList(authConfig.getPropertyList("oauth2.scope")));
details.setAuthenticationScheme(AuthenticationScheme.query);
details.setClientAuthenticationScheme(AuthenticationScheme.form);
return details;
}
@Bean
public OAuth2ClientAuthenticationProcessingFilter
oauth2ClientAuthenticationProcessingFilter() {
// Used to obtain access token from authorization server (AS)
OAuth2RestOperations restTemplate = new OAuth2RestTemplate(
authorizationCodeResource(),
oauth2ClientContext);
OAuth2ClientAuthenticationProcessingFilter filter =
new OAuth2ClientAuthenticationProcessingFilter(authConfig.getProperty("oauth2.filterCallbackPath"));
filter.setRestTemplate(restTemplate);
// Set a service that validates an OAuth2 access token
// We can use either Google API's UserInfo or TokenInfo
// For this, we chose to use UserInfo service
filter.setTokenServices(googleUserInfoTokenServices());
return filter;
}
@Bean
public GoogleUserInfoTokenServices googleUserInfoTokenServices() {
GoogleUserInfoTokenServices userInfoTokenServices =
new GoogleUserInfoTokenServices(authConfig.getProperty("oauth2.userInfoUri"), authConfig.getProperty("oauth2.clientId"));
// TODO Configure bean to use local database to read authorities
// userInfoTokenServices.setAuthoritiesExtractor(authoritiesExtractor);
return userInfoTokenServices;
}
@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
// May need an OAuth2AuthenticationEntryPoint for non-browser clients
return new LoginUrlAuthenticationEntryPoint(authConfig.getProperty("oauth2.filterCallbackPath"));
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/", "/static/**", "/webjars/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint());
http
.antMatcher("/auth/oauth/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.addFilterAfter(
oauth2ClientContextFilter,
ExceptionTranslationFilter.class)
.addFilterBefore(
oauth2ClientAuthenticationProcessingFilter(),
FilterSecurityInterceptor.class)
.anonymous()
.disable();
}
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return new NoopAuthenticationManager();
}
}
private static class NoopAuthenticationManager implements AuthenticationManager {
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
throw new UnsupportedOperationException(
"No authentication should be done with this AuthenticationManager");
}
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
访问回调 url api/auth/oauth/callback
时,出现以下异常:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton
在搜索 SO 时,建议的解决方案是添加 RequestContextListener
bean,但即使添加之后我也没有成功。
一个 solution 也建议使用 FilterRegistrationBean
但我没有使用 Springboot 所以我不确定它是否能解决我的问题。
完整异常跟踪:
2018-02-22 12:47:36,440 - /api/auth/oauth/callback org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:355) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192) at com.sun.proxy.$Proxy64.getAccessToken(Unknown Source) at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:169) at org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:105) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter.doFilter(OAuth2ClientContextFilter.java:60) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:83) at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:364) at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.eclipse.jetty.server.Server.handle(Server.java:497) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257) at org.eclipse.jetty.io.AbstractConnection.run(AbstractConnection.java:540) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:555) at java.lang.Thread.run(Unknown Source) Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) at org.springframework.web.context.request.SessionScope.get(SessionScope.java:91) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340) ... 55 more
我解决了这个问题。而且在这个Springboot
的时代,用稍微老一点的系统的人可能会觉得答案有用,所以分享一下。
RequestContextListener
需要像这样在码头配置中添加:
context.addEventListener(new RequestContextListener());
我将它添加到我的安全配置文件中,如下所示:
@Bean
@Order(0)
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
有人会觉得这很有用,在 AbstractAnnotationConfigDispatcherServletInitializer 实现中添加以下内容 class:
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addListener(new RequestContextListener());
}