当前位置: 首页 > 知识库问答 >
问题:

尽管定义了RequestContextListener,但创建名为'ScopedTarget.OAuth2ClientContext'的bean时出错

吕自怡
2023-03-14
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();
}

在访问回调urlapi/auth/oauth/callback时,我得到以下异常:

org.springframework.beans.factory.BeanCreationException:创建名为“ScopedTarget.oauth2ClientContext”的bean时出错:当前线程的作用域“session”不活动;如果您打算从单个对象引用这个bean,请考虑为它定义一个限定作用域的代理

完全异常跟踪:

共有1个答案

景宏富
2023-03-14

我解决了问题。在这个Springboot的时代,正在使用稍旧系统的人可能会发现答案很有用,所以可以分享它。

在jetty配置中需要添加RequestContextListener,如下所示:

context.addEventListener(new RequestContextListener());

我将其添加到安全配置文件中,如下所示:

@Bean
@Order(0)
public RequestContextListener requestContextListener() {
    return new RequestContextListener();
}
 类似资料: