Spring Boot-Cycle bean依赖问题

时间:2019-06-30 22:31:58

标签: java spring spring-boot

我的问题是-可能我的依赖项定义错误,但是找不到错误!

┌─────┐
|  jwtAuthorizationTokenFilter defined in file [\JwtAuthorizationTokenFilter.class]
↑     ↓
|  jwtUserDetailsService (security.service.JwtUserDetailsService.authenticationManager)
↑     ↓
|  webSecurityConfig (security.WebSecurityConfig.authenticationTokenFilter)
└─────┘

JwtAuthorizationTokenFilter.class

@Component
    public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {

        private final Logger logger = LoggerFactory.getLogger(this.getClass());

        private final UserDetailsService userDetailsService;
        private final JwtTokenUtil jwtTokenUtil;
        private final String tokenHeader;

        public JwtAuthorizationTokenFilter(@Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, @Value("${jwt.header}") String tokenHeader) {
            this.userDetailsService = userDetailsService;
            this.jwtTokenUtil = jwtTokenUtil;
            this.tokenHeader = tokenHeader;
        }

        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
            logger.debug("processing authentication for '{}'", request.getRequestURL());

            System.out.println("JwtAuthorTokenFilter Header request " + request.getHeader(this.tokenHeader));
            final String requestHeader = request.getHeader(this.tokenHeader);

            String username = null;
            String authToken = null;
            if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
                authToken = requestHeader.substring(7);
                System.out.println("Auth token " + authToken);
                try {
                    username = jwtTokenUtil.getUsernameFromToken(authToken);
                } catch (IllegalArgumentException e) {
                    logger.error("an error occurred during getting username from token", e);
                } catch (ExpiredJwtException e) {
                    logger.warn("the token is expired and not valid anymore", e);
                }
            } else {
                logger.warn("couldn't find bearer string, will ignore the header");
            }

            logger.debug("checking authentication for user '{}'", username);
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                logger.debug("security context was null, so authorizing user");

                UserDetails userDetails;
                try {
                    userDetails = userDetailsService.loadUserByUsername(username);
                } catch (UsernameNotFoundException e) {
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
                    return;
                }

                if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    logger.info("authorized user '{}', setting security context", username);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }

            chain.doFilter(request, response);
        }
    }

JwtUserDetailsS​​ervice

@Service("jwtUserDetailsService")
public class JwtUserDetailsService implements UserDetailsService {

    @Autowired
    private UserDAO userDAO;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userDAO.findByUsername(username);

        if (user == null) {
            throw new UsernameNotFoundException(String.format("No user found with username '%s'.", username));
        } else {
            return JwtUserFactory.create(user);
        }
    }

    public void authenticate(String username, String password) {
        Objects.requireNonNull(username);
        Objects.requireNonNull(password);

        try {
            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
        } catch (DisabledException e) {
            throw new AuthenticationException("User is disabled!", e);
        } catch (BadCredentialsException e) {
            throw new AuthenticationException("Bad credentials!", e);
        }
    }
}

WebSecurityConfig

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    @Autowired
    JwtAuthorizationTokenFilter authenticationTokenFilter;

    @Value("${jwt.header}")
    private String tokenHeader;

    @Value("${jwt.route.authentication.path}")
    private String authenticationPath;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(jwtUserDetailsService)
            .passwordEncoder(passwordEncoderBean());
    }

    @Bean
    public PasswordEncoder passwordEncoderBean() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
            .csrf().disable()
            .exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
                .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .authorizeRequests()
            .antMatchers("/api/auth/**").permitAll()
            .anyRequest().authenticated();

       httpSecurity
            .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

    }

    @Override
    public void configure(WebSecurity web) throws Exception {

        web
            .ignoring()
            .antMatchers(
                HttpMethod.POST,
                authenticationPath
            )
            .and()
            .ignoring()
            .antMatchers(
                HttpMethod.GET,
                "/",
                "/*.html",
                "/favicon.ico",
                "/**/*.html",
                "/**/*.css",
                "/**/*.js"
            );
    }
}

我尝试了所有事情:)删除了AuthenticationManager,重新配置了全局配置-但没有任何动作。也许我的Spring依赖知识不深,所以这就是我遇到这个常见问题的原因。

但是也许您知道如何解决该问题?

1 个答案:

答案 0 :(得分:2)

代替过滤器上的@Component,您可以尝试使用@Bean在配置中创建它。从我的角度来看,您依赖于WebSecurityConfig中声明的userDetailService,要构造它需要其AutoWired bean。

TL; DR,如果在JwtAuthorizationTokenFilter中使用@Autowired JwtAuthorizationTokenFilter authenticationTokenFilter;

,则不能使用@Autowired private JwtUserDetailsService jwtUserDetailsService

尝试:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    @Value("${jwt.header}")
    private String tokenHeader;

    @Autowired
    private JwtTokenUtil jwtTokenUtil

    @Value("${jwt.route.authentication.path}")
    private String authenticationPath;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(jwtUserDetailsService)
            .passwordEncoder(passwordEncoderBean());
    }

    @Bean
    public PasswordEncoder passwordEncoderBean() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
            .csrf().disable()
            .exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
                .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .authorizeRequests()
            .antMatchers("/api/auth/**").permitAll()
            .anyRequest().authenticated();

       httpSecurity
            .addFilterBefore(new JwtAuthorizationTokenFilter(jwtUserDetailsService, tokenUtil, tokenHeader), UsernamePasswordAuthenticationFilter.class);

    }

    @Override
    public void configure(WebSecurity web) throws Exception {

        web
            .ignoring()
            .antMatchers(
                HttpMethod.POST,
                authenticationPath
            )
            .and()
            .ignoring()
            .antMatchers(
                HttpMethod.GET,
                "/",
                "/*.html",
                "/favicon.ico",
                "/**/*.html",
                "/**/*.css",
                "/**/*.js"
            );
    }
}

删除@Component:


    public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {

        private final Logger logger = LoggerFactory.getLogger(this.getClass());

        private final UserDetailsService userDetailsService;
        private final JwtTokenUtil jwtTokenUtil;
        private final String tokenHeader;

        public JwtAuthorizationTokenFilter(UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, @Value("${jwt.header}") String tokenHeader) {
            this.userDetailsService = userDetailsService;
            this.jwtTokenUtil = jwtTokenUtil;
            this.tokenHeader = tokenHeader;
        }


[.....]