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

dxpyg8gm  于 2021-09-29  发布在  Java
关注(0)|答案(1)|浏览(353)

有了多租户应用程序,我想在没有租户的情况下尽早结束任何请求。

设置/场景

我使用spring会话和Spring Security 运行spring boot(web)。
在我的例子中,我有几种策略来确定租户,租户Fromx,租户Fromy。。全部按订单运行 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 该过滤器之后的所有其他过滤器都将被调用。
例如 SessionRepositoryFilter 被召唤 Ordered.HIGHEST_PRECEDENCE+50 然后是 Spring 保安 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 将响应设置为suspended以完成任何其他链(这是我不想要的)。
这似乎仍然不正确,那么如何以正确的方式进行呢?或者这完全是一个概念上的缺陷?

beq87vna

beq87vna1#

通过显式调用或引发异常发送错误,将导致将请求分派到应用程序的错误页面处理,该处理将再次调用筛选器进行分派。设置状态是正确的做法。

相关问题