我有一个OAuth2实现,可以对授权类型=密码正常运行。现在,我需要添加一种逻辑,如果用户先前登录,则限制相同的用户/密码组合才能再次登录。为此,我进行了研究并发现我要创建一个扩展DefaultTokenServices类的新类(MyDefaultTokenService),然后在重写的createAccessToken方法中添加逻辑。但是出于某些原因,当我调试和测试时,我没有达到MyDefaultTokenService类中放置的断点。它总是命中Springboot的DefaultTokenServices类。我不知道我要去哪里错了,请有人帮忙。
AuthorizationConfiguration.java
package com.company.config; import java.util.Arrays; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.context.EnvironmentAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.env.Environment; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.TokenRequest; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; import com.alcord.enums.Authorities; import com.alcord.model.Account; @Configuration @EnableAuthorizationServer public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware { private static final String ENV_OAUTH = "authentication.oauth."; private static final String PROP_CLIENTID = "clientid"; private static final String PROP_SECRET = "secret"; private static final String PROP_TOKEN_VALIDITY_SECONDS = "tokenValidityInSeconds"; private RelaxedPropertyResolver propertyResolver; @Autowired private DataSource dataSource; @Bean public TokenStore tokenStore() { return new JdbcTokenStore(dataSource); } @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain(); tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer())); endpoints.tokenStore(tokenStore()).tokenEnhancer(tokenEnhancerChain) .authenticationManager(authenticationManager); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory().withClient(propertyResolver.getProperty(PROP_CLIENTID)).scopes("read", "write") .authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_DRIVER.name(), Authorities.ROLE_PASSENGER.name()) .authorizedGrantTypes("password", "refresh_token", "authorization_code", "implicit") .secret(propertyResolver.getProperty(PROP_SECRET)).accessTokenValiditySeconds( propertyResolver.getProperty(PROP_TOKEN_VALIDITY_SECONDS, Integer.class, 1800)); } @Override public void setEnvironment(Environment environment) { this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_OAUTH); } @Bean public TokenEnhancer tokenEnhancer() { return new CustomTokenEnhancer(); } @Bean @Primary public DefaultTokenServices tokenServices() { MyTokenService tokenService = new MyTokenService(); tokenService.setTokenStore(tokenStore()); tokenService.setSupportRefreshToken(true); tokenService.setTokenEnhancer(tokenEnhancer()); return tokenService; } class MyTokenService extends DefaultTokenServices { public MyTokenService() { } @Override public OAuth2AccessToken readAccessToken(String accessToken) { return super.readAccessToken(accessToken); } @Override public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException { OAuth2AccessToken token = super.createAccessToken(authentication); Account account = (Account) authentication.getPrincipal(); // This is where I will add my logic when it hits the breakpoint. return token; } @Override public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest) throws AuthenticationException { OAuth2AccessToken token = super.refreshAccessToken(refreshTokenValue, tokenRequest); return token; } } }
资源服务器配置
package com.company.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import com.alcord.security.CustomAuthenticationEntryPoint; import com.alcord.security.CustomLogoutSuccessHandler; @Configuration @EnableResourceServer @EnableGlobalMethodSecurity(prePostEnabled = true) public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { // The DefaultTokenServices bean provided at the AuthorizationConfig @Autowired private DefaultTokenServices tokenServices; // The TokenStore bean provided at the AuthorizationConfig @Autowired private TokenStore tokenStore; @Autowired private CustomAuthenticationEntryPoint customAuthenticationEntryPoint; @Autowired private CustomLogoutSuccessHandler customLogoutSuccessHandler; @Override public void configure(HttpSecurity http) throws Exception { http.exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint).and().logout() .logoutUrl("/oauth/logout").logoutSuccessHandler(customLogoutSuccessHandler).and().csrf().disable() .headers().frameOptions().disable().exceptionHandling().and().sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll().antMatchers("/api/v1/login/**").permitAll() .antMatchers("/api/v1/admin/**").permitAll().antMatchers("/api/v1/test/**").permitAll() .antMatchers("/oauth/token").permitAll().antMatchers("/api/**").authenticated(); } @Override public void configure(ResourceServerSecurityConfigurer resources) { resources.tokenServices(tokenServices).tokenStore(tokenStore).resourceId("oauth2_id"); } }
答案。缺少在configure方法中添加tokenServices()
@Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain(); tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer())); endpoints.tokenStore(tokenStore()).tokenServices(tokenServices()).tokenEnhancer(tokenEnhancerChain) .authenticationManager(authenticationManager); }