【问题标题】:Spring security OAuth stackoverflowException春季安全 OAuth stackoverflowException
【发布时间】:2014-08-20 23:37:46
【问题描述】:

我想将 Spring 安全性与 OAuth 和 JWT 令牌一起使用。 我目前的配置是:

@Configuration
@EnableResourceServer
public class OAuth2ServerConfig {

@Configuration
@EnableWebSecurity
protected static class ResourceServer extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        // @formatter:off   
        http.anonymous().disable()
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
            .exceptionHandling()
            .accessDeniedHandler(accessDeniedHandler()) // handle access denied in general (for example comming from @PreAuthorization
            .authenticationEntryPoint(entryPointBean()) // handle authentication exceptions for unauthorized calls.
            .and()
        .authorizeRequests()
            // only allow this three endpoint to NOT be authenticated.
            .antMatchers(HttpMethod.POST, "/users").permitAll()
            .antMatchers(HttpMethod.POST, "/users/authenticate").permitAll()
             .antMatchers(HttpMethod.GET, "/users/inviationCode/{code}").permitAll()
            .antMatchers(HttpMethod.POST, "/**").fullyAuthenticated()
            .antMatchers(HttpMethod.GET, "/**").fullyAuthenticated()
            .antMatchers(HttpMethod.PUT, "/**").fullyAuthenticated()
            .antMatchers(HttpMethod.DELETE, "/**").fullyAuthenticated()
            .antMatchers(HttpMethod.OPTIONS, "/**").fullyAuthenticated()
            .and()
            .addFilterBefore(filterBean(), AbstractPreAuthenticatedProcessingFilter.class)
            .requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/oauth/**")))
            .authorizeRequests().anyRequest().authenticated().expressionHandler(new OAuth2WebSecurityExpressionHandler())
            .and()
        .csrf().disable(); // for chrome/FF plugins to work. for now we shouldn't face any problem since there is no point that JS can be injected into our page...
        // @formatter:on
    }
    
    @Bean(name="authenticationManager")
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManagerBean();
    }
    
    @Bean
    @Autowired
    AccessDeniedHandler accessDeniedHandler() {
        return new AccessDeniedExceptionHandler();
    }
    
    @Bean
    @Autowired
    AuthenticationEntryPoint entryPointBean() {
        return new UnauthorizedEntryPoint();
    }
    
    @Bean
    @Autowired
    GenericFilterBean filterBean() {
        return new XAuthTokenFilter();
    }
    
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Bean(name="userAuthenticationManager")
    public UserAuthenticationService userAuthenticationManager() throws Exception {
        return new UserAuthenticationService();
    }

}


@Configuration
@EnableAuthorizationServer
public static class OAuth2Config extends AuthorizationServerConfigurerAdapter {

    @Autowired
    @Qualifier("authenticationManager")
    private AuthenticationManager authenticationManager;
    
    @Autowired
    @Qualifier("restDataSource")
    private BasicDataSource restDataSource;

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        return new JwtAccessTokenConverter();
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess(
                "hasAuthority('ROLE_TRUSTED_CLIENT')");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager).accessTokenConverter(accessTokenConverter());
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
            .withClient("test")
                .authorizedGrantTypes("client_credentials", "password")
                .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
                .scopes("read", "write")
                .secret("secret");
    }

  }
}

这些配置基于官方springgithub repo 我现在面临的问题是,每当我尝试使用此 url 获取令牌时:

http://myapplication.com/test/oauth/token?grant_type=password

我收到以下错误:

java.lang.StackOverflowError
at org.apache.commons.logging.impl.Jdk14Logger.isDebugEnabled(Jdk14Logger.java:214)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:144)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:427)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:177)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:427)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:177)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:427)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:177)

这似乎是身份验证过程中的一个循环,但老实说,我可以找到它的根源。 我想使用的流程如下:

  • 用户要求一个令牌传递用户名、密码和客户端(可能在 base64 中)。 (方法发布)
  • 正在对用户进行身份验证。
  • 向用户返回一个 JWT 令牌。
  • 用户在标头中携带令牌。

有人可以就适当的配置提出建议吗?

最好的

【问题讨论】:

    标签: java spring spring-security oauth-2.0


    【解决方案1】:

    找到了问题,它是特定于身份验证管理器的。 这是我的工作配置:

    @Configuration
    @ComponentScan
    @EnableResourceServer
    @Import({SecurityConfig.class})
    public class OAuth2ServerConfig {
    
    @Configuration
    @EnableAuthorizationServer
    protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
    
        @Autowired
        private AuthenticationManager authenticationManager;
    
        @Autowired
        @Qualifier("restDataSource")
        private DataSource datasource;
    
        @Bean
        public JwtAccessTokenConverter accessTokenConverter() {
            return new JwtAccessTokenConverter();
        }
    
        @Bean
        public CustomJwtTokenStore tokenStore() {
            return new CustomJwtTokenStore();
        }
    
    //      @Bean
    //      public JdbcTokenStore tokenStore() {
    //          return new JdbcTokenStore(datasource);
    //      }
    
        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess(
                    "hasAuthority('ROLE_TRUSTED_CLIENT')");
        }
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore()).accessTokenConverter(accessTokenConverter());
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                .withClient("my-trusted-client")
                    .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
                    .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
                    .scopes("read", "write", "trust")
                    .accessTokenValiditySeconds(60)
            .and()
                .withClient("my-client-with-registered-redirect")
                    .authorizedGrantTypes("authorization_code")
                    .authorities("ROLE_CLIENT")
                    .scopes("read", "trust")
                    .redirectUris("http://anywhere?key=value")
            .and()
                .withClient("my-client-with-secret")
                    .authorizedGrantTypes("client_credentials", "password")
                    .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
                    .scopes("read", "write")
                    .secret("secret");
        }
    
    }
    }
    

    使用安全配置:

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;
    
    @Autowired
    private AccessDeniedHandler accessDeniedHandler;
    
    @Autowired
    private GenericFilterBean filter;
    
    
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/webjars/**", "/images/**", "/oauth/uncache_approvals", "/oauth/cache_approvals");
    }
    
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userAuthenticationManager()).passwordEncoder(passwordEncoder());
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
          .exceptionHandling()
            .accessDeniedHandler(accessDeniedHandler) // handle access denied in general (for example comming from @PreAuthorization
            .authenticationEntryPoint(authenticationEntryPoint) // handle authentication exceptions for unauthorized calls.
        .and()
          .authorizeRequests()
            .antMatchers("/xxx/**").fullyAuthenticated()
            .antMatchers("/xxx/**").fullyAuthenticated()
            .antMatchers("/xxx/**").fullyAuthenticated()
         .and()
           .csrf().disable();;
    }
    
    @Bean
    @Autowired
    ApplicationListener<AbstractAuthenticationEvent> loggerBean() {
        return new org.springframework.security.authentication.event.LoggerListener();
    }
    
    @Bean
    @Autowired
    AccessDeniedHandler accessDeniedHandler() {
        return new AccessDeniedExceptionHandler();
    }
    
    @Bean
    @Autowired
    AuthenticationEntryPoint entryPointBean() {
        return new UnauthorizedEntryPoint();
    }
    
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Bean(name="userAuthenticationManager")
    public UserDetailsService userAuthenticationManager() throws Exception {
        return new UserServiceImpl();
    }
    
    @Bean
    public UserService userService() {
        return new UserServiceImpl();
    }   
    }
    

    【讨论】:

    猜你喜欢
    • 2017-03-24
    • 1970-01-01
    • 2013-12-22
    • 2014-02-02
    • 2012-12-13
    • 2017-11-30
    • 2021-05-12
    相关资源
    最近更新 更多