Spring GraphQL 身份验证错误处理

问题描述 投票:0回答:1

我在我的项目中使用 Spring GraphQLSpring Security。我正在使用 JWT 对用户进行身份验证,因此我有一个安全过滤器来检查令牌的有效性。当token无效时,会抛出异常。 我试图将异常消息作为有效的 graphQL 响应返回,但我得到的只是:

{
  "errors": {
    "message": "Failed to execute 'text' on 'Response': body stream already read",
    "stack": "TypeError: Failed to execute 'text' on 'Response': body stream already read\n    at http://localhost:8080/graphiql?path=/graphql:78:33"
  }
}

我在控制台中收到的错误是这样的:

com.auth0.jwt.exceptions.JWTDecodeException: The input is not a valid base 64 encoded string.

所以,我希望在“错误”“消息”中。

这是安全配置:

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

    private final AppUserDetailsService appUserDetailsService;
    private final JwtFilter jwtFilter;

    public SecurityConfig(AppUserDetailsService appUserDetailsService, JwtFilter jwtFilter) {
        this.appUserDetailsService = appUserDetailsService;
        this.jwtFilter = jwtFilter;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(appUserDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/auth").permitAll()
                .antMatchers("/graphiql").permitAll()
                .antMatchers("/graphql").permitAll()
                .anyRequest().authenticated()
                .and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
    }

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

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

这是 jwtFilter:

@Log4j2
@Component
public class JwtFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtil;
    private final AppUserDetailsService userDetailsService;

    public JwtFilter(JwtUtil jwtUtil, AppUserDetailsService userDetailsService) {
        this.jwtUtil = jwtUtil;
        this.userDetailsService = userDetailsService;
    }

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

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

        String username = null;
        String jwt = null;

        try {
            if (header != null && header.startsWith("Bearer ")) {
                jwt = header.substring(7);
                username = jwtUtil.getUsername(jwt);
            }

            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
                if (jwtUtil.validateToken(jwt, userDetails)) {
                    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());
                    authenticationToken.setDetails(
                            new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                }
            }
        } catch (Exception ex) {
            log.error(ex.getMessage());
            throw ex;
        }
        filterChain.doFilter(request, response);
    }
}

有谁知道我怎样才能实现这一目标?

谢谢!

spring-security jwt spring-graphql
1个回答
0
投票

您可以使用

@GraphQlExceptionHandler
带注释的方法编写新的全局异常处理程序,并使用
GraphQLError
从那里自定义构建错误消息。有时,此类方法可能无法捕获过滤器抛出的错误,因为 graphql-java 引擎可能尚未在过滤器级别调用。要捕获此类错误,请在项目中定义一个
ErrorWebExceptionHandler
的 bean。

© www.soinside.com 2019 - 2024. All rights reserved.