Springboot应用返回401而不是500。

huangapple go评论75阅读模式
英文:

Springboot App returns 401 instead of 500

问题

我最近从SpringBoot 2.7.4迁移到了SpringBoot 3.1.0。

我在安全配置中进行了一些更改,因为一些类已经被弃用。

一切都正常工作,但在Spring应用程序控制器中引发的任何错误都不会返回给调用方。响应始终是401未经授权。

我甚至不确定要分享哪些文件,因为这非常奇怪。

任何帮助都将不胜感激。

即使被标记为忽略的端点在发生异常时也会返回401。

我还为配置每个请求的RequestId而创建了一个过滤器。

@Data
@EqualsAndHashCode(callSuper = false)
public class Slf4jMDCFilter extends OncePerRequestFilter {
    // ...
}

它的用法如下:

@Configuration
public class Slf4jMDCFilterConfiguration {
    // ...
}

我确认以前不会发生这种情况,而是返回500内部服务器错误。

英文:

I recently migrated from SpringBoot 2.7.4 to SpringBoot 3.1.0.

I made some changes in the Security Config as some of the classes were deprecated.

Everything works alright but any error that is raised in the Spring App Controller is not returned to the caller. The response is always 401 Unauthorized.

I'm not even sure which files to share as this is extremely weird.

Any help is appreciated

Even endpoints marked as ignored return with a 401 in case of an exception.

@EnableWebSecurity
@Configuration
public class SecurityConfig {

    @Value( "${auth0.audience}" )
    private String audience;

    @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
    private String issuer;


    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers("/v1/noauth/**", "/actuator/**");
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests((authz) -> authz
                        .requestMatchers("/v1/**").authenticated()
                )
                .oauth2ResourceServer((oauth2) -> oauth2
                        .jwt((jwt) -> jwt
                                .decoder(jwtDecoder())
                        )
                )
                .cors(Customizer.withDefaults())
                .csrf(AbstractHttpConfigurer::disable);
        return http.build();
    }

    @Bean
    JwtDecoder jwtDecoder() {
        /*
        By default, Spring Security does not validate the "aud" claim of the token, to ensure that this token is
        indeed intended for our app. Adding our own validator is easy to do:
        */

        NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder)
                JwtDecoders.fromOidcIssuerLocation(issuer);

        OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(audience);
        OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuer);
        OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);

        jwtDecoder.setJwtValidator(withAudience);

        return jwtDecoder;
    }
}

I also have a Filter for configuring RequestId for each request

@Data
@EqualsAndHashCode(callSuper = false)
public class Slf4jMDCFilter extends OncePerRequestFilter {
    private final String responseHeader;
    private final String mdcTokenKey;
    private final String requestHeader;

    public Slf4jMDCFilter(String responseHeader, String mdcTokenKey, String requestHeader){
        this.responseHeader = responseHeader;
        this.mdcTokenKey = mdcTokenKey;
        this.requestHeader = requestHeader;
    }

    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain)
            throws java.io.IOException, ServletException {
        try {
            final String token;
            if (StringUtils.hasText(requestHeader) && StringUtils.hasText(request.getHeader(requestHeader))) {
                token = URLEncoder.encode(request.getHeader(requestHeader));
            } else {
                token = UUID.randomUUID().toString().toUpperCase();
            }
            MDC.put(mdcTokenKey, token);
            if (StringUtils.hasText(responseHeader)) {
                response.addHeader(responseHeader, token);
            }
            chain.doFilter(request, response);
        } finally {
            MDC.remove(mdcTokenKey);
        }
    }
}

which is used as follows

@Configuration
public class Slf4jMDCFilterConfiguration {

    public static final String DEFAULT_RESPONSE_TOKEN_HEADER = "ResponseToken";

    private final String responseHeader = DEFAULT_RESPONSE_TOKEN_HEADER;
    private final String mdcTokenKey = Util.DEFAULT_MDC_UUID_TOKEN_KEY();

    @Value( "${config.slf4jfilter.requestHeader}" )
    private String requestHeader;

    @Bean
    public FilterRegistrationBean servletRegistrationBean() {
        final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        final Slf4jMDCFilter log4jMDCFilterFilter = new Slf4jMDCFilter(responseHeader, mdcTokenKey, requestHeader);
        registrationBean.setFilter(log4jMDCFilterFilter);
        registrationBean.setOrder(2);
        return registrationBean;
    }
}

I confirmed that earlier this was not happening and a 500 with INTERNAL_SERVER_ERROR was returned.

答案1

得分: 1

你应该检查认证和授权。请检查登录令牌是否正确,或者是否已将其作为参数传递给相应的接口。

英文:

You should check the authentication and authorization. Please check if the login token is correct or if it has been passed as a parameter to the corresponding interface.

答案2

得分: 0

使用 authorizeRequests 而不是 authorizeHttpRequests 解决了这个问题。

我从这里得到了这个想法:https://github.com/spring-projects/spring-boot/issues/33341。

如果有人能告诉我为什么这个更改修复了问题,我会接受那个答案。

谢谢。

英文:

Using authorizeRequests instead of authorizeHttpRequests solved the issue.

I got the idea from here: https://github.com/spring-projects/spring-boot/issues/33341.

If someone can tell me why this change fixed the issue, I'll accept that answer.

Thanks

huangapple
  • 本文由 发表于 2023年6月1日 14:17:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76379146.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定