Spring Security的loadUserByUsername方法在UsernameNotFoundException上连续调用

时间:2019-07-14 14:11:51

标签: spring spring-boot spring-security

我在代码中使用UserDetailsS​​ervice来生成用户身份验证令牌。使用正确的凭据可以很好地工作,但是当出现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]

0 个答案:

没有答案