首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >弹簧引导错误:超出maxRedirects。可能被困在重定向循环中

弹簧引导错误:超出maxRedirects。可能被困在重定向循环中
EN

Stack Overflow用户
提问于 2020-05-24 17:47:04
回答 2查看 10.9K关注 0票数 2

我试图在spring引导中执行JWT auth,并且请求被困在重定向循环中。

JWTAuthenticationProvider

代码语言:javascript
运行
复制
@Component
public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public boolean supports(Class<?> authentication) {
        return (JwtAuthenticationToken.class.isAssignableFrom(authentication));
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    }

    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication;
        String token = jwtAuthenticationToken.getToken();

        JwtParsedUser parsedUser = jwtUtil.parseToken(token);

        if (parsedUser == null) {
            throw new JwtException("JWT token is not valid");
        }
        UserDetails user = User.withUsername(parsedUser.getUserName()).password("temp_password").authorities(parsedUser.getRole()).build();
        return user;
    }

JwtAuthenticationFilter

代码语言:javascript
运行
复制
public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super("/**");
        this.setAuthenticationManager(authenticationManager);
    }

    @Override
    protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
        return true;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {

        String header = request.getHeader("Authorization");

        if (header == null || !header.startsWith("Bearer ")) {
            throw new JwtException("No JWT token found in request headers");
        }

        String authToken = header.substring(7);

        JwtAuthenticationToken authRequest = new JwtAuthenticationToken(authToken);

        return getAuthenticationManager().authenticate(authRequest);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request,

            HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
        super.successfulAuthentication(request, response, chain, authResult);

        chain.doFilter(request, response);
    }

}

SecurityConfiguration

代码语言:javascript
运行
复制
@Configuration
@EnableWebSecurity(debug = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationProvider jwtAuthenticationProvider;

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(jwtAuthenticationProvider);

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable().authorizeRequests().antMatchers("/secured-resource-1/**", "/secured-resource-2/**")
                .hasRole("ADMIN").antMatchers("/secured-resource-2/**").hasRole("ADMIN").and().formLogin()
                .successHandler(new AuthenticationSuccessHandler()).and().httpBasic().and().exceptionHandling()
                .accessDeniedHandler(new CustomAccessDeniedHandler()).authenticationEntryPoint(getBasicAuthEntryPoint())
                .and()
                .addFilterBefore(new JwtAuthenticationFilter(authenticationManager()),
                        FilterSecurityInterceptor.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Bean
    public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint() {
        return new CustomBasicAuthenticationEntryPoint();
    }
}

MainController

代码语言:javascript
运行
复制
@RestController
public class MainController {
    @Autowired
    private JwtUtil jwtUtil;

    @GetMapping("/secured-resource-1")
    public String securedResource1() {
        return "Secured resource1";
    }
}

当我使用有效的JWT令牌到达端点时,代码会从过滤器循环到提供者类,并以错误结束:

代码语言:javascript
运行
复制
Exceeded maxRedirects. Probably stuck in a redirect loop http://localhost:8000/ error. 

调试日志显示以下错误:

代码语言:javascript
运行
复制
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: Cannot call sendError() after the response has been committed] with root cause

java.lang.IllegalStateException: Cannot call sendError() after the response has been committed

有什么建议吗?我在这里遗漏了什么。提前谢谢。

EN

回答 2

Stack Overflow用户

发布于 2020-05-25 11:55:41

我相信这样做的原因是因为您没有为bean JwtAuthenticationFilter实际设置JwtAuthenticationFilter,因为它没有实际设置,所以它会一直在超级和链上循环,而当需要发送错误时,因为响应已经用super() chain.doFilter写好了,就会失败,因为一旦写了响应,就不能再次写入错误call sendError() after the response has been committed

在设置此选项之前,在SecurityConfiguration中更正此错误

代码语言:javascript
运行
复制
.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()),
                        FilterSecurityInterceptor.class)

实例化过滤器并设置它的成功管理器如下

代码语言:javascript
运行
复制
JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager()),FilterSecurityInterceptor.class);

jwtAuthenticationFilter.setAuthenticationSuccessHandler(new CustomAuthenticationSuccessHandler());

现在使用上面的变量来设置过滤器。这是一个很好的参考项目:https://gitlab.com/palmapps/jwt-spring-security-demo/-/tree/master/

票数 2
EN

Stack Overflow用户

发布于 2020-05-31 12:58:48

我用另一种方法解决了这个问题。在JwtAuthenticationFilter类中,我们需要在上下文中设置身份验证对象并调用chain.doFilter。可以跳过调用super.successfulAuthentication,因为我们已经重写了实现。

代码语言:javascript
运行
复制
 @Override
   protected void successfulAuthentication(HttpServletRequest request,

   HttpServletResponse response, FilterChain chain, Authentication authResult)
                throws IOException, ServletException {
            //super.successfulAuthentication(request, response, chain, authResult);
            SecurityContextHolder.getContext().setAuthentication(authResult);
            chain.doFilter(request, response);
        }

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super("/**");
        this.setAuthenticationManager(authenticationManager);
        //this.setAuthenticationSuccessHandler(new JwtAuthenticationSuccessHandler());
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61989976

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档