我有一个 Spring Boot 项目,其中包含使用 JWT 过滤器保护的工作 REST 端点。例如,GET 请求需要不记名令牌,然后返回用户数据。所有 REST 端点都按预期工作。现在我们想要实现 GraphQL 查询以用于将来的数据获取。
这就是问题所在。 如果 /graphql 端点在安全配置中未受到保护
.authorizeHttpRequests(
authorizeRequests ->
authorizeRequests
.requestMatchers("/graphql/**")
.permitAll() // Whitelist
.anyRequest().authenticated() // Everything else should be authenticated
)
查询通过,我得到了我想要的数据。但是,如果我现在将 GraphQL 端点从这个“白名单”中删除,则每个请求(无论有没有有效的访问令牌)都会以 403 的形式返回。Postman 或 IntelliJ 控制台中也没有错误消息,我可以在其中追溯到哪里此代码来自。
如需更多资源,这是我的完整安全配置:
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final AuthenticationProvider authenticationProvider;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(
authorizeRequests ->
authorizeRequests
.requestMatchers("/graphql/**")
.permitAll()
.anyRequest().authenticated()
)
.sessionManagement(
sessionManagement ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
}
这是我的 JWT 过滤器:
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(
@NotNull HttpServletRequest request,
@NotNull HttpServletResponse response,
@NotNull FilterChain filterChain)
throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
final String jwt;
final String userEmail;
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
jwt = authHeader.substring(7);// beginIndex is 7 bc "Bearer " is 7
userEmail = jwtService.extractUserEmail(jwt);
if (userEmail != null
&& SecurityContextHolder.getContext().getAuthentication() == null) { // check f if user is already authenticated
UserDetails userDetails = userDetailsService.loadUserByUsername(userEmail);
if (jwtService.isTokenValid(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
如果您将授权请求链更改为
...
authorizeRequests
.anyRequest()
.permitAll()
...
它应该让所有请求通过,然后您可以使用 Spring Security 处理您的授权。