java.lang.StackOverflower错误

szqfcxe2  于 2021-10-10  发布在  Java
关注(0)|答案(0)|浏览(255)

我正试图在SpringMVC应用程序中实现jwt令牌身份验证。在此更改之前,身份验证仅使用basic auth进行。现在我想把基本auth和jwt结合起来。这就是迄今为止所做的事情。

@Configuration
@Order(200)
@Description("authentication for opt")
public static class ApiOperatorWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {

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

        web
                .ignoring()
                .antMatchers("/resources/**");
    }

    protected void configure(HttpSecurity http) throws Exception {

        http
                .antMatcher("/opt/**");

        http
                .authorizeRequests()
                .antMatchers("/opt/internal/authenticate").permitAll()
                .antMatchers("/opt/main/v1/**").permitAll()
                .antMatchers("/opt/main/v2/ex").permitAll() 
                .antMatchers("/opt/main/v3/ex").permitAll()
                .antMatchers("/opt/main/v3/ex").permitAll()
                .antMatchers("/opt/v4").permitAll()
                .antMatchers("/opt/**").hasRole("OPERATOR")
                .anyRequest().authenticated()
                .accessDecisionManager(accessDecisionManager())
                .and()
                .csrf().disable()
                .httpBasic()
                .authenticationEntryPoint(authenticationEntryPoint());
        http
                .authenticationProvider(operatorsAuthenticationProvider())
                //.authenticationProvider(operatorsJwtAuthenticationProvider())
                .authenticationProvider(googleAuthenticationProvider());

                    .sessionManagement().sessionCreationPolicy(STATELESS);
            http.addFilterBefore(jwtRequestFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    public AuthenticationProvider operatorsAuthenticationProvider() {

        return new OperatorsAuthenticationProviderImpl();
    }

    @Bean
    public JwtRequestFilter jwtRequestFilter(){
        return new JwtRequestFilter();
    }

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

    @Bean
    public JwtUtil jwtUtil() throws Exception{
        return new JwtUtil();
    }

    @Bean
    public AuthenticationProvider operatorsJwtAuthenticationProvider() {
        return new OperatorsJwtAuthenticationProviderImpl();
    }

    @Bean
    public AuthenticationProvider googleAuthenticationProvider() {

        return new GoogleAuthenticationProviderImpl();
    }

    @Bean
    protected AuthenticationEntryPoint authenticationEntryPoint() {

        OperatorsRestAuthenticationEntryPoint authenticationEntryPoint = new OperatorsRestAuthenticationEntryPoint();
        authenticationEntryPoint.setRealmName("operators");

        return authenticationEntryPoint;
    }
}

在我的控制器中,我创建了 /authenticate 端点并自动连接authenticationmanager

@Autowired
AuthenticationManager authenticationManager;

@Autowired
JwtUtil jwtUtil;

@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtAuthenticationRequest authenticationRequest) throws Exception {

try {
    authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword())
    );
}
catch (BadCredentialsException e) {
    throw new Exception("Incorrect username or password", e);
}

final UserDetails userDetails = authenticationService
        .loadUserByUsername(authenticationRequest.getUsername());

final String jwt = jwtUtil.generateToken(userDetails);

    return ResponseEntity.ok(new JwtAuthenticationResponse(jwt));
}

JWT过滤器

@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    @Autowired
    OperatorsAuthenticationService authenticationService;

    @Autowired
    JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {

            final String authorizationHeader = request.getHeader("Authorization");

            String username = null;
            String jwt = null;

            if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
                jwt = authorizationHeader.substring(7);
                username = jwtUtil.extractUsername(jwt);
            }

            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

                UserDetails userDetails = this.authenticationService.loadUserByUsername(username);

                if (jwtUtil.validateToken(jwt, userDetails)) {

                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());
                    usernamePasswordAuthenticationToken
                            .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                }else{
                    throw new Exception("Auth error");
                }
            }
            filterChain.doFilter(request, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

现在的问题是:当我尝试使用基本身份验证进行身份验证时,系统递归地调用 operatorsAuthenticationProvider 最后我得到了一个 java.lang.StackOverflowError ```
java.lang.StackOverflowError
at java.lang.reflect.Method.specificToStringHeader(Method.java:369)
at java.lang.reflect.Executable.sharedToString(Executable.java:121)
at java.lang.reflect.Method.toString(Method.java:361)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at org.springframework.remoting.rmi.RmiClientInterceptor.doInvoke(RmiClientInterceptor.java:357)
at org.springframework.remoting.rmi.RmiClientInterceptor.invoke(RmiClientInterceptor.java:260)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy363.authenticate(Unknown Source)
at sun.reflect.GeneratedMethodAccessor230.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy364.authenticate(Unknown Source)
at com.mydom.myapp.api.security.defaultimpl.OperatorsAuthenticationProviderImpl.authenticate(OperatorsAuthenticationProviderImpl.java:33)

我注意到,在注解authenticationmanagerbeanbean的声明时,basic auth与以前一样工作正常。
有人知道发生了什么吗?authenticationmanagerbean声明有什么问题?谢谢

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题