在SpringDetail上通过UserDetailsS​​ervice进行堆栈溢出

时间:2019-07-17 10:00:10

标签: spring spring-boot spring-security oauth-2.0

我正在尝试创建一个实现oauth2.0的项目。我正在使用Springboot 2,我的客户端存储在JDBC中,并使用JWT令牌存储。

该应用程序运行,但是当我向/ oauth / token发送POST请求时,出现内部服务器错误。我尝试调试代码,似乎UserDetailsS​​ervice委托人正在委托自己,造成了堆栈溢出错误。

这是我的授权服务器:

@Configuration @EnableAuthorizationServer @EnableConfigurationProperties(SecurityProperties.class) public class AuthorizationServerConfiguration
        extends AuthorizationServerConfigurerAdapter
{

    @Autowired private PasswordEncoder passwordEncoder;
    @Autowired private AuthenticationManager authenticationManager;
    @Autowired private UserDetailsService userDetailsService;

    @Autowired private SecurityProperties securityProperties;
    JwtAccessTokenConverter jwtAccessTokenConverter;
    TokenStore tokenStore;

    @Bean
    public TokenStore tokenStore()
    {
        if(tokenStore == null)
        {
            tokenStore = new JwtTokenStore(accessTokenConverter());
        }
        return tokenStore;
    }

    @Bean
    public DefaultTokenServices tokenServices(final TokenStore tokenStore, final ClientDetailsService clientDetailsService)
    {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setTokenStore(tokenStore);
        tokenServices.setClientDetailsService(clientDetailsService);
        tokenServices.setAuthenticationManager(this.authenticationManager);
        return tokenServices;
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter()
    {
        if(jwtAccessTokenConverter != null)
        {
            return jwtAccessTokenConverter;
        }

        SecurityProperties.JwtProperties jwtProperties = securityProperties.getJwt();
        KeyPair keyPair = keyPair(jwtProperties, keyStoreKeyFactory(jwtProperties));

        jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setKeyPair(keyPair);

        jwtAccessTokenConverter.setSigningKey("montyKey");

        return jwtAccessTokenConverter;
    }

    @Bean
    public DataSource dataSource()
    {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/OauthTestDB?useSSL=false");
        dataSource.setUsername("root");
        dataSource.setPassword("MyPassword99");
        return dataSource;
    }

    @Override
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception
    {
        clients.jdbc(dataSource());
    }

    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer endpoints)
    {
        endpoints.authenticationManager(this.authenticationManager)
                .accessTokenConverter(accessTokenConverter())
                .userDetailsService(this.userDetailsService)
                .tokenStore(tokenStore());
    }

    @Override
    public void configure(final AuthorizationServerSecurityConfigurer oauthServer)
    {
        oauthServer.passwordEncoder(this.passwordEncoder)
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()");
    }

    private KeyPair keyPair(SecurityProperties.JwtProperties jwtProperties, KeyStoreKeyFactory keyStoreKeyFactory)
    {
        return keyStoreKeyFactory.getKeyPair(jwtProperties.getKeyPairAlias(), jwtProperties.getKeyPairPassword().toCharArray());
    }

    private KeyStoreKeyFactory keyStoreKeyFactory(SecurityProperties.JwtProperties jwtProperties)
    {
        return new KeyStoreKeyFactory(jwtProperties.getKeyStore(), jwtProperties.getKeyStorePassword().toCharArray());
    }
}

WebSecurityConfiguration:

@EnableWebSecurity public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter
{

    private PasswordEncoder passwordEncoder;
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception
    {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception
    {
        return super.authenticationManagerBean();
    }

    @Bean
    public PasswordEncoder passwordEncoder()
    {
        if(passwordEncoder == null)
        {
            passwordEncoder = DefaultPasswordEncoderFactories.createDelegatingPasswordEncoder();
        }
        return passwordEncoder;
    }

    @Bean
    public UserDetailsService userDetailsService(DataSource dataSource)
    {
        if(userDetailsService == null)
        {
            userDetailsService = new JdbcDaoImpl();
            ((JdbcDaoImpl) userDetailsService).setDataSource(dataSource);
        }
        return userDetailsService;
    }

}

错误日志如下:

[DEBUG] 2019-07-17 10:40:09.326 [http-nio-9000-exec-1] FilterChainProxy - /oauth/token?grant_type=password&username=user&password=pass reached end of additional filter chain; proceeding with original chain
[DEBUG] 2019-07-17 10:40:09.327 [http-nio-9000-exec-1] DispatcherServlet - POST "/oauth/token?grant_type=password&username=user&password=pass", parameters={masked}

[DEBUG] 2019-07-17 10:40:09.332 [http-nio-9000-exec-1] FrameworkEndpointHandlerMapping - Mapped to public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException

[DEBUG] 2019-07-17 10:40:09.339 [http-nio-9000-exec-1] JdbcTemplate - Executing prepared SQL query
[DEBUG] 2019-07-17 10:40:09.339 [http-nio-9000-exec-1] JdbcTemplate - Executing prepared SQL statement [select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?]
[DEBUG] 2019-07-17 10:40:09.339 [http-nio-9000-exec-1] DataSourceUtils - Fetching JDBC Connection from DataSource
[DEBUG] 2019-07-17 10:40:09.339 [http-nio-9000-exec-1] DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/OauthTestDB?useSSL=false]

[DEBUG] 2019-07-17 10:40:09.345 [http-nio-9000-exec-1] JdbcTemplate - Executing prepared SQL query
[DEBUG] 2019-07-17 10:40:09.345 [http-nio-9000-exec-1] JdbcTemplate - Executing prepared SQL statement [select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?]
[DEBUG] 2019-07-17 10:40:09.345 [http-nio-9000-exec-1] DataSourceUtils - Fetching JDBC Connection from DataSource
[DEBUG] 2019-07-17 10:40:09.345 [http-nio-9000-exec-1] DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/OauthTestDB?useSSL=false]

[DEBUG] 2019-07-17 10:40:09.354 [http-nio-9000-exec-1] JdbcTemplate - Executing prepared SQL query
[DEBUG] 2019-07-17 10:40:09.354 [http-nio-9000-exec-1] JdbcTemplate - Executing prepared SQL statement [select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?]
[DEBUG] 2019-07-17 10:40:09.354 [http-nio-9000-exec-1] DataSourceUtils - Fetching JDBC Connection from DataSource
[DEBUG] 2019-07-17 10:40:09.354 [http-nio-9000-exec-1] DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/OauthTestDB?useSSL=false]

[DEBUG] 2019-07-17 10:40:09.359 [http-nio-9000-exec-1] ResourceOwnerPasswordTokenGranter - Getting access token for: clientId
[DEBUG] 2019-07-17 10:40:09.359 [http-nio-9000-exec-1] ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider

[DEBUG] 2019-07-17 10:40:09.422 [http-nio-9000-exec-1] ExceptionHandlerExceptionResolver - Using @ExceptionHandler public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.exceptions.OAuth2Exception> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.handleException(java.lang.Exception) throws java.lang.Exception
[WARN ] 2019-07-17 10:40:09.423 [http-nio-9000-exec-1] TokenEndpoint - Handling error: NestedServletException, Handler dispatch failed; nested exception is java.lang.StackOverflowError

[DEBUG] 2019-07-17 10:40:09.436 [http-nio-9000-exec-1] HttpEntityMethodProcessor - Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
[DEBUG] 2019-07-17 10:40:09.436 [http-nio-9000-exec-1] HttpEntityMethodProcessor - Writing [error="server_error", error_description="Internal Server Error"]

1 个答案:

答案 0 :(得分:0)

我最终只是删除了以下配置:

@Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception
    {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }