我在代码中使用UserDetailsService来生成用户身份验证令牌。使用正确的凭据可以很好地工作,但是当出现UsernameNotFoundException异常时,会连续调用loadUserByUsername。
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
@EnableAuthorizationServer
@EnableGlobalMethodSecurity(securedEnabled = true)
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Resource
private UserDetailsService userDetailsService;
private final TokenStore tokenStore;
private final DataSource dataSource;
private final AuthenticationManager authenticationManager;
public OAuth2Config(UserDetailsService userDetailsService, TokenStore tokenStore, DataSource dataSource,
@Lazy AuthenticationManager authenticationManager) {
this.userDetailsService = userDetailsService;
this.tokenStore = tokenStore;
this.dataSource = dataSource;
this.authenticationManager = authenticationManager;
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer configurer) throws Exception {
configurer.authenticationManager(authenticationManager);
configurer.userDetailsService(userDetailsService);
configurer.tokenStore(tokenStore);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
}
}
import com.aimbeyond.model.Groups;
import com.aimbeyond.model.User;
import com.aimbeyond.repository.GroupRepository;
import com.aimbeyond.repository.UserRepository;
import com.aimbeyond.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@Service("userDetailsService")
public class UserServiceImpl implements UserDetailsService, UserService {
private final static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
@Autowired
private GroupRepository groupRepository;
private final UserRepository userRepository;
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = null;
List getAuthority = null;
try {
user = userRepository.findOneByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("Invalid username or password." + username);
}
String pwdExpiryDt = user.getPasswordExpiry();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dt = new Date();
String currentDt = dateFormat.format(dt);
/*if (pwdExpiryDt != null) {
logger.info("Current DateTime" + currentDt + "===" + "Password Expiry date" + pwdExpiryDt + "====" + pwdExpiryDt.compareTo(currentDt));
if (currentDt.compareTo(pwdExpiryDt) > 0) {
throw new UsernameNotFoundException("Password is expired.");
}
}*/
Groups gr = groupRepository.findBygroupId(user.getGroupId());
getAuthority = Arrays.asList(new SimpleGrantedAuthority(gr.getGroupName()));
user.setLastLogin(currentDt);
userRepository.save(user);
} catch (UsernameNotFoundException ex) {
logger.info("!!!!!!!!!!!!!!!!!!! " + ex.getLocalizedMessage());
throw ex;
} catch (Exception ex) {
ex.printStackTrace();
logger.error("User is unable to login.");
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthority);
}
当我使用不正确的凭据访问http://localhost:9001/auth/oauth/token时,它将引发内部服务器错误,并在抛出UsernameNotFoundException时无限循环中调用loadUserByUsername。
019-07-14 19:28:35.155 INFO 19883 --- [nio-8000-exec-1] com.aimbeyond.impl.UserServiceImpl : !!!!!!!!!!!!!!!!!!! Invalid username or password.ram.kumar1@aimbeyond.com
2019-07-14 19:28:35.261 INFO 19883 --- [nio-8000-exec-1] com.aimbeyond.impl.UserServiceImpl : !!!!!!!!!!!!!!!!!!! Invalid username or password.ram.kumar1@aimbeyond.com
2019-07-14 19:28:35.385 INFO 19883 --- [nio-8000-exec-1] com.aimbeyond.impl.UserServiceImpl : !!!!!!!!!!!!!!!!!!! Invalid username or password.ram.kumar1@aimbeyond.com
2019-07-14 19:28:35.492 INFO 19883 --- [nio-8000-exec-1] com.aimbeyond.impl.UserServiceImpl : !!!!!!!!!!!!!!!!!!! Invalid username or password.ram.kumar1@aimbeyond.com
2019-07-14 19:28:35.593 INFO 19883 --- [nio-8000-exec-1] com.aimbeyond.impl.UserServiceImpl : !!!!!!!!!!!!!!!!!!! Invalid username or password.ram.kumar1@aimbeyond.com
2019-07-14 19:28:35.697 INFO 19883 --- [nio-8000-exec-1] com.aimbeyond.impl.UserServiceImpl : !!!!!!!!!!!!!!!!!!! Invalid username or password.ram.kumar1@aimbeyond.com
2019-07-14 19:28:35.809 INFO 19883 --- [nio-8000-exec-1] com.aimbeyond.impl.UserServiceImpl : !!!!!!!!!!!!!!!!!!! Invalid username or password.ram.kumar1@aimbeyond.com
2019-07-14 19:28:35.962 ERROR 19883 --- [nio-8000-exec-1] o.s.s.o.provider.endpoint.TokenEndpoint : Handling error: NestedServletException, Handler dispatch failed; nested exception is java.lang.StackOverflowError
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.StackOverflowError
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1006) ~[spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) ~[spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) [spring-webmvc-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:158) [spring-boot-actuator-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:126) [spring-boot-actuator-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:111) [spring-boot-actuator-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90) [spring-boot-actuator-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:215) [spring-security-web-5.0.6.RELEASE.jar:5.0.6.RELEASE]