spring-boot - 如何在早期 servlet/spring boot 过滤器中强制结束过滤器链

标签 spring-boot spring-mvc spring-security spring-session spring-filter

拥有 Multi-Tenancy 应用程序,我想尽早结束没有租户的任何请求。

设置/场景

我使用 Spring session 和 Spring Security 运行 Spring Boot(Web)。

就我而言,我有多种策略来确定租户,TenantFromX、TenantFromY .. 全部按订单 Ordered.HIGHEST_PRECEDENCE 运行 - 尽可能早。

根据订单 Ordered.HIGHEST_PRECEDENCE+1,我运行 TenantMustExistFilter 过滤器来验证任何策略实际上是否匹配/找到租户定义

@Log4j2
@Component
@RequiredArgsConstructor
// After TenantFromX(min) but before SessionRepositoryFilter(Session) which is min+50
@Order(Ordered.HIGHEST_PRECEDENCE + 1)
public class TenantMandatoryFilter extends GenericFilterBean
{
  @Override
  public void doFilter(
    ServletRequest request, ServletResponse response,
    FilterChain filterChain
  ) throws ServletException, IOException
  {
    if (TenantStore.getInitMode().isEmpty()) {
      throw new NoTenantException("No tenant identified for request - request blocked");
    }

    try {
      filterChain.doFilter(request, response);
    } finally {
      TenantStore.clear();
    }
  }
}

问题/问题

尽管我抛出运行时异常 NoTenantException 该过滤器之后的所有其他过滤器仍然会被调用。

例如,在 Ordered.HIGHEST_PRECEDENCE+50 上调用 SessionRepositoryFilter,然后触发 spring security FilterProxyChain

TenantMandatoryFilter 验证失败后,如何有效地停止链? 我期望 return;Exception 或者只是不调用 filterChain.doFilter(request, response); 足以结束链式执行。

我对这里的流程或想法有误解吗?

尝试

我可以通过替换成功结束链条

if (TenantStore.getInitMode().isEmpty()) {
  throw new NoTenantException("No tenant identified for request - request blocked");
}

if (TenantStore.getInitMode().isEmpty()) {
  response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
  return;
}

有趣的是,下面的代码不起作用,尽管它在语义上看起来更正确。它不起作用意味着,它会在此之后调用 SessionRepositoryFilterFilterChainProxy

if (TenantStore.getInitMode().isEmpty()) {
  response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid tenant");
  return;
}

我认为这是因为 sendError 将响应设置为挂起以完成任何其他链(这是我不想要的)。

看起来仍然不对,那么如何以正确的方式做到这一点?或者这完全是一个概念缺陷?

最佳答案

通过显式调用或抛出异常来发送错误,将导致请求被分派(dispatch)到应用程序的错误页面处理,这将再次调用该分派(dispatch)的过滤器。设置状态是正确的做法。

关于spring-boot - 如何在早期 servlet/spring boot 过滤器中强制结束过滤器链,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68146232/

相关文章:

Java - 安全性已开启,但我仍然可以发送我想要的任何请求

spring - 基于 spring-boot 项目构建可部署的 WAR

mysql - 如何将 mysql-client 连接到我的 Spring Boot 应用程序

Spring + PostgreSQL > 多个 SLF4J 绑定(bind)

java - 使用 Spring Cloud 连接器访问 CloudFoundry 用户提供的服务

spring-security - 用于 Google 登录的 Spring Security OAuth2 Java 配置

testing - 模拟 Grails Spring Security 登录用户

grails - Spring Boot-java.lang.ClassNotFoundException:javax.servlet.ServletContext并且无法启动EmbeddedWebApplicationContext

java - 同时使用Spring Data Hadoop + Spring MVC时出错

java - Spring Security for Active Directory 搜索为 'userPrincipalName'——有办法改变这个吗?