我有一个使用XML的Spring-Security OAuth2配置,我试图将其转换为基于Java的配置。这是一个简单的密码授予方案,授权服务器和资源服务器位于同一个应用程序中。 XML配置工作正常。但是,当访问/ oauth / token端点以请求令牌时,基于Java的配置会产生StackOverflowError,并在
上循环org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:446)
org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:192).
是什么给出了?
Java配置:
@Configuration
@EnableWebSecurity
public class MyAppSpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("supersecret")
.roles("ROLE_USER", "ROLE_ADMIN");
}
@Bean
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManagerBean();
}
@Configuration
@EnableAuthorizationServer
protected static class OAuth2AuthConfig extends AuthorizationServerConfigurerAdapter {
@Autowired private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("myclient")
.secret("password123")
.authorizedGrantTypes("password", "refresh_token")
.authorities("ROLE_APP")
.scopes("myapp")
.accessTokenValiditySeconds(60 * 60); // 1 hour
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
@Configuration
@EnableResourceServer
protected static class OAuth2ResourceConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/services/**").and()
.authorizeRequests().antMatchers("/services/**").authenticated();
}
}
}
XML配置(工作):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<sec:http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager">
<sec:intercept-url pattern="/oauth/token" access="isFullyAuthenticated()"/>
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER"/>
<sec:access-denied-handler ref="oauthAccessDeniedHandler"/>
<sec:anonymous enabled="false"/>
<sec:csrf disabled="true"/>
</sec:http>
<sec:http pattern="/services/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint">
<sec:intercept-url pattern="/services/**" access="hasRole('ROLE_USER')"/>
<sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER"/>
<sec:access-denied-handler ref="oauthAccessDeniedHandler"/>
<sec:anonymous enabled="false"/>
<sec:csrf disabled="true"/>
</sec:http>
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="myapp"/>
</bean>
<bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="myapp/client"/>
<property name="typeName" value="Basic"/>
</bean>
<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager"/>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/>
<bean class="org.springframework.security.access.vote.RoleVoter"/>
<bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</list>
</constructor-arg>
</bean>
<sec:authentication-manager id="clientAuthenticationManager">
<sec:authentication-provider user-service-ref="clientDetailsUserService"/>
</sec:authentication-manager>
<bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails"/>
</bean>
<bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider>
<sec:user-service>
<sec:user name="admin" password="supersecret" authorities="ROLE_USER,ROLE_ADMIN"/>
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore"/>
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore"/>
<property name="supportRefreshToken" value="true"/>
<property name="accessTokenValiditySeconds" value="3600"/>
<property name="clientDetailsService" ref="clientDetails"/>
</bean>
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:refresh-token/>
<oauth:password/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" resource-id="myapp" token-services-ref="tokenServices"/>
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="myapp" secret="password123" authorized-grant-types="password,refresh_token" scope="myapp" authorities="ROLE_APP"/>
</oauth:client-details-service>
</beans>
我知道XML中指定的很多东西都是通过@EnableAuthorizationServer和@EnableResourceServer默认的,但显然我仍然遗漏了一些东西。我在样本应用程序和单元测试中来回走动。但似乎在这些配置中似乎还有更多与Spring Boot相关的魔法。
这是Spring 4.2.3,Spring Security 4.0.3和Spring Security OAuth 2.0.8
答案 0 :(得分:1)
如果要将AuthenticationManager实例公开为bean,则需要覆盖public AuthenticationManager authenticationManagerBean()
而不是protected AuthenticationManager authenticationManager()
。