Posso excluir alguns URLs concretos de <url-pattern> dentro de <filter-mapping>?
127
Quero que um filtro de concreto seja aplicado a todos os URLs, exceto um concreto (ou seja, /*exceto /specialpath).
Existe a possibilidade de fazer isso?
Código de amostra:
<filter><filter-name>SomeFilter</filter-name><filter-class>org.somproject.AFilter</filter-class></filter><filter-mapping><filter-name>SomeFilter</filter-name><url-pattern>/*</url-pattern><!-- the question is: how to modify this line? --><dispatcher>REQUEST</dispatcher><dispatcher>FORWARD</dispatcher></filter-mapping>
A API Servlet padrão não suporta esse recurso. Você pode usar um filtro de URL de reescrita como o de Tuckey (que é muito semelhante ao HTTPD do Apache mod_rewrite) ou adicionar uma verificação no doFilter()método de escuta do filtro /*.
String path =((HttpServletRequest) request).getRequestURI();if(path.startsWith("/specialpath/")){
chain.doFilter(request, response);// Just continue chain.}else{// Do your business stuff here for all paths other than /specialpath.}
Se necessário, é possível especificar os caminhos a serem ignorados como um init-paramfiltro, para que você possa controlá-lo da mesma web.xmlmaneira. Você pode obtê-lo no filtro da seguinte maneira:
Se o filtro fizer parte da API de terceiros e, portanto, você não puder modificá-lo, mapeie-o de forma mais específica url-pattern, por exemplo, /otherfilterpath/*e crie um novo filtro no /*qual encaminha para o caminho correspondente ao filtro de terceiros.
Para evitar que esse filtro se auto-identifique em um loop infinito, é necessário deixá-lo ouvir (despachar) REQUESTapenas e o filtro de terceiros FORWARDsomente.
Meu problema é que o filtro não é meu, é da biblioteca de componentes.
Roman
4
O Ypu deve pegar o filtro da biblioteca do componente e estendê-lo para adicionar o código que você deseja usar para executar as exclusões.
Gbtimmon
@BalusC Se o "/ specialpath" serve apenas um recurso estático como js, css, etc, chain.doFilter () torna a resposta mais lenta? Existe um método para servir o recurso diretamente sem encadear o filtro?
BenhurCD
@BenhurCD: Eu realmente não tenho ideia de como você poderia chegar a essa preocupação com o desempenho.
BalusC
13
Usei uma abordagem descrita por Eric Daugherty : criei um servlet especial que sempre responde com o código 403 e coloca seu mapeamento antes do geral.
Essa abordagem funciona quando você deseja impedir um determinado filtro e todos os seguintes. Deve funcionar bem se você, por exemplo. deseja veicular algum conteúdo como recursos estáticos no contêiner do servlet em vez de deixar a lógica do aplicativo (por meio de um filtro como o GuiceFilter):
Mapeie a pasta com seus arquivos de recursos estáticos para o servlet padrão. Crie um filtro de servlet e coloque-o antes do GuiceFilter no seu web.xml. No filtro criado, você pode separar entre encaminhar algumas solicitações para o GuiceFilter e outras diretamente para o despachante. Exemplo a seguir ...
Tentei ir com sua solução, mas para os arquivos que aplico o filtro e quebro a cadeia, recebo o seguinte erro; Exceção não capturada lançada pelo filtro Static Resource Filter: java.io.FileNotFoundException. Alguma idéia do porquê?
Shamaleyte
Nas configurações de múltiplos contextos, o uso .getRequestURI()será interrompido (provavelmente causando um erro 404) porque é .getRequestDispatcherresolvido em relação ao caminho do contexto . Se o seu caminho de contexto for /a, então, no seu exemplo, o URI da solicitação seria /a/statice o uso getRequestDispatcher("/a/static")fará com que ele seja resolvido /a/a/static. Correção: use em .getServletPath()vez de .getRequestURI(). Vou enviar uma edição para corrigir isso, mas só queria deixar um comentário FYI
Reid
3
Eu não acho que você pode, a única outra alternativa de configuração é enumerar os caminhos que você deseja filtrar, portanto, em vez de /*adicionar alguns para /this/*e /that/*etc, mas isso não levará a uma solução suficiente quando você tiver muito desses caminhos.
O que você pode fazer é adicionar um parâmetro ao filtro, fornecendo uma expressão (como uma expressão regular) que é usada para ignorar a funcionalidade do filtro para os caminhos correspondentes. O contêiner de servlet ainda chamará seu filtro para esses URLs, mas você terá melhor controle sobre a configuração.
Editar
Agora que você mencionou que não tem controle sobre o filtro, o que você pode fazer é herdar os supermétodos de chamada de filtro em seus métodos, exceto quando o caminho da URL que você deseja pular estiver presente e seguir a cadeia de filtros como @BalusC proposta, ou compilar um filtro que instancia seu filtro e delega nas mesmas circunstâncias. Nos dois casos, os parâmetros do filtro incluem o parâmetro de expressão que você adiciona e os do filtro que você herda ou delega.
A vantagem de criar um filtro de delegação (um invólucro) é que você pode adicionar a classe de filtro do filtro empacotado como parâmetro e reutilizá-lo em outras situações como esta.
Se, por qualquer motivo, você não puder alterar o mapeamento do filtro original ("/ *" no meu caso) e estiver enviando para um filtro de terceiros imutável, poderá achar útil o seguinte:
Intercepte o caminho a ser ignorado
Pule para e execute o último anel da cadeia de filtros (o próprio servlet)
O salto é feito via reflexão, inspecionando as instâncias do contêiner no modo de depuração
Usei uma abordagem descrita por Eric Daugherty : criei um servlet especial que sempre responde com o código 403 e coloca seu mapeamento antes do geral.
Fragmento de mapeamento:
E a classe de servlet:
fonte
Essa abordagem funciona quando você deseja impedir um determinado filtro e todos os seguintes. Deve funcionar bem se você, por exemplo. deseja veicular algum conteúdo como recursos estáticos no contêiner do servlet em vez de deixar a lógica do aplicativo (por meio de um filtro como o GuiceFilter):
Mapeie a pasta com seus arquivos de recursos estáticos para o servlet padrão. Crie um filtro de servlet e coloque-o antes do GuiceFilter no seu web.xml. No filtro criado, você pode separar entre encaminhar algumas solicitações para o GuiceFilter e outras diretamente para o despachante. Exemplo a seguir ...
web.xml
StaticResourceFilter.class
Infelizmente, se você quiser pular uma única etapa da cadeia de filtros, mantendo as seguintes, isso não funcionará.
fonte
.getRequestURI()
será interrompido (provavelmente causando um erro 404) porque é.getRequestDispatcher
resolvido em relação ao caminho do contexto . Se o seu caminho de contexto for/a
, então, no seu exemplo, o URI da solicitação seria/a/static
e o usogetRequestDispatcher("/a/static")
fará com que ele seja resolvido/a/a/static
. Correção: use em.getServletPath()
vez de.getRequestURI()
. Vou enviar uma edição para corrigir isso, mas só queria deixar um comentário FYIEu não acho que você pode, a única outra alternativa de configuração é enumerar os caminhos que você deseja filtrar, portanto, em vez de
/*
adicionar alguns para/this/*
e/that/*
etc, mas isso não levará a uma solução suficiente quando você tiver muito desses caminhos.O que você pode fazer é adicionar um parâmetro ao filtro, fornecendo uma expressão (como uma expressão regular) que é usada para ignorar a funcionalidade do filtro para os caminhos correspondentes. O contêiner de servlet ainda chamará seu filtro para esses URLs, mas você terá melhor controle sobre a configuração.
Editar
Agora que você mencionou que não tem controle sobre o filtro, o que você pode fazer é herdar os
super
métodos de chamada de filtro em seus métodos, exceto quando o caminho da URL que você deseja pular estiver presente e seguir a cadeia de filtros como @BalusC proposta, ou compilar um filtro que instancia seu filtro e delega nas mesmas circunstâncias. Nos dois casos, os parâmetros do filtro incluem o parâmetro de expressão que você adiciona e os do filtro que você herda ou delega.A vantagem de criar um filtro de delegação (um invólucro) é que você pode adicionar a classe de filtro do filtro empacotado como parâmetro e reutilizá-lo em outras situações como esta.
fonte
Eu também tive que filtrar com base no padrão de URL (/ {servicename} / api / stats /) no código java.
Mas é bizarro que o servlet não suporte padrão de URL diferente de (/ *). Esse deve ser um caso muito comum para APIs de servlet!
fonte
Eu encontrei o mesmo problema, mas encontro uma resposta mostrando abaixo.
web.xml
filter.java
Dessa forma, você não precisa assediar a classe Filter concreta.
fonte
Se, por qualquer motivo, você não puder alterar o mapeamento do filtro original ("/ *" no meu caso) e estiver enviando para um filtro de terceiros imutável, poderá achar útil o seguinte:
O seguinte funciona no Weblogic 12.1.3:
fonte