Qual é o objetivo do DelegatingFilterProxy do Spring MVC?

120

Vejo isso nos meus aplicativos Spring MVC web.xml:

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

Estou tentando descobrir por que está lá e se é realmente necessário.

Encontrei essa explicação nos documentos do Spring, mas isso não me ajuda a entender:

Parece sugerir que esse componente é a "cola" entre os servlets definidos em web.xmle os componentes definidos na primavera applicationContext.xml.

7.1 DelegatingFilterProxy

Ao usar filtros de servlet, obviamente você precisa declará-los no seu web.xml, ou eles serão ignorados pelo contêiner do servlet. No Spring Security, as classes de filtro também são Spring beans definidas no contexto do aplicativo e, portanto, capazes de tirar proveito dos ricos recursos de injeção de dependências e interfaces do ciclo de vida do Spring. O Spring's DelegatingFilterProxyfornece o link entre web.xmle o contexto do aplicativo.

Ao usar o DelegatingFilterProxy, você verá algo assim no web.xmlarquivo:

<filter>
   <filter-name>myFilter</filter-name>
   <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
   <filter-name>myFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

Observe que o filtro é realmente uma DelegatingFilterProxyclasse, e não a classe que realmente implementará a lógica do filtro. O que DelegatingFilterProxyfaz é delegar os métodos do Filter através de um bean que é obtido no contexto do aplicativo Spring. Isso permite que o bean se beneficie do suporte ao ciclo de vida do contexto do aplicativo da web Spring e da flexibilidade de configuração. O bean deve ser implementado javax.servlet.Filtere deve ter o mesmo nome que o do elemento filter-name. Leia o Javadoc para DelegatingFilterProxy para obter mais informações

Então, se eu tirar isso da minha web.xml, o que vai acontecer? Meus servlets não poderão se comunicar com o contêiner Spring? **

Thomas
fonte

Respostas:

127

Há algum tipo de mágica aqui, mas no final, tudo é um programa determinístico.

O DelegatingFilterProxy é um Filtro, como foi explicado acima, cujo objetivo é " delegar a um bean gerenciado pelo Spring que implementa a interface Filter ", ou seja, ele encontra um bean ("bean de destino" ou "delegar") no aplicativo Spring contexto e invoca-o. Como isso é possível? Como esse bean implementa o javax.servlet.Filter, seu método doFilter é chamado.

Qual bean é chamado? the DelegatingFilterProxy "Suporta um" targetBeanName "[...]", especificando o nome do bean de destino no contexto do aplicativo Spring. "

Como você viu em seu web.xml, o nome do bean é " springSecurityFilterChain " .

Portanto, no contexto de um aplicativo Web, um Filtro instancia um bean chamado "springSecurityFilterChain" no contexto do aplicativo e, em seguida, delega a ele por meio do método doFilter ().

Lembre-se de que o contexto do seu aplicativo é definido com os arquivos ALL THE APPLICATION-CONTEXT (XML). Por exemplo: applicationContext.xml AND applicationContext-security.xml.

Portanto, tente encontrar um bean chamado "springSecurityFilterChain" no último ...

... e provavelmente você não pode (por exemplo, se você seguiu um tutorial ou se configurou a segurança usando o Roo)

Aqui está a mágica: há um novo elemento para configurar a segurança , algo como

<http auto-config="true" use-expressions="true"> 

como é permitido por http://www.springframework.org/schema/security/spring-security-3.0.xsd , fará o truque.

Quando o Spring carrega o contexto do aplicativo usando arquivos XML, se encontrar um elemento, ele tentará configurar a segurança HTTP, ou seja, uma pilha de filtros e URLs protegidas e registrar o FilterChainProxy chamado "springSecurityFilterChain".

Como alternativa, você pode definir o bean da maneira clássica, ou seja:

<beans:bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">

Mas é menos recomendado, pois você precisa fazer muitas configurações (todos os filtros que você usará. E há mais de uma dúzia deles)

jbbarquero
fonte
"applicationContext-security.xml AND applicationContext-security.xml" é o mesmo nome de arquivo duas vezes.
precisa saber é
Graças musikk (eu acho que você pode editar o post diretamente)
jbbarquero
Esta foi a explicação que eu estava procurando o tempo todo e esclareceu as coisas para mim.
precisa saber é o seguinte
@jbbarquero: Você está certo, mas eu não tinha certeza de qual deveria ser a versão correta. Costumo deixar isso para o autor original corrigir, para não alterar inadvertidamente o significado.
MusiKk
ESTÁ BEM. De qualquer forma, agradeço muito sua ajuda para melhorar minha resposta. Obrigado novamente, musiKk
jbbarquero
73

Você sabe o que é um filtro de servlet e como ele funciona? É uma parte muito útil das especificações do servlet, permitindo aplicar conceitos do tipo AOP ao atendimento de solicitações HTTP. Muitas estruturas usam implementações de filtro para várias coisas, e não é incomum encontrar implementações personalizadas delas porque são muito simples de escrever e úteis. Em um aplicativo Spring, a maioria das coisas que seu aplicativo pode fazer está nos seus beans Spring. Uma instância de filtro, no entanto, é controlada pelo contêiner Servlet. O contêiner instancia, inicializa e destrói. A especificação Servlet não requer nenhum tipo de integração com o Spring; portanto, você fica com um conceito realmente útil (filtros), sem uma maneira conveniente de vinculá-lo ao seu aplicativo Spring e aos beans que fazem o trabalho.

Digite o DelegatingFilterProxy. Você escreve uma implementação de Filtro e o torna um bean Spring, mas, em vez de adicionar sua própria classe Filter ao web.xml, usa o DelegatingFilterProxy e fornece o nome do bean do seu filtro no contexto Spring. (Se você não fornecer um nome explicitamente, ele usará o "nome do filtro".) Em tempo de execução, o DelegatingFilterProxy lida com a complexidade de encontrar a implementação real - a que você escreveu e configurou no Spring - e encaminhar solicitações para ela . Portanto, no tempo de execução, é como se você tivesse listado seu filtro no web.xml, mas você tem a vantagem de poder conectá-lo como qualquer outro bean Spring.

Se você remover esse mapeamento de filtro do seu web.xml, tudo continuará funcionando, mas nenhum dos seus URLs estará protegido. (Isso pressupõe que o nome "springSecurityFilterChain" descreva com precisão o que ele faz.) Isso ocorre porque esse mapeamento está filtrando todas as solicitações recebidas e transferindo-as para um filtro de segurança definido no seu contexto do Spring.

Ryan Stewart
fonte
Obrigado por postar este comentário esclarecedor. Estou aprendendo o Spring Security agora, tentando entendê-lo o suficiente para fazer personalizações. Eu não tinha idéia do que eram os filtros de servlet ou o que são filtros de molas. Sua parte sobre o AOP deixa claro POR QUE alguém teria filtros em vez de usar apenas servlets ........ para que você não precise escrever o mesmo pré / pós-processamento repetidamente em cada servlet / recurso
Steve
Uau. Essa explicação é exatamente o que eu precisava. Obrigado por compartilhar seu conhecimento.
Charles Morin
@ Ryan Stewart se eu tiver dois beans implementa a interface Filter no applicationContext e quero executar em uma ordem, então como posso fazer isso?
Abhishek Nayak
@skaffman se eu tiver dois beans implementa a interface Filter no applicationContext e quero executar em uma ordem, então como posso fazer isso?
Abhishek Nayak
44

O que são filtros de servlet?

Os filtros de servlet são, em geral, um conceito Java WebApp. Você pode ter filtros de servlet em qualquer aplicativo da web, independentemente de usar ou não a estrutura Spring em seu aplicativo.

Esses filtros podem interceptar solicitações antes de atingirem o servlet de destino. Você pode implementar funcionalidades comuns, como autorização, em filtros de servlet. Depois de implementado, você pode configurar o filtro em seu web.xml para ser aplicado a um servlet específico, padrões de URL de solicitação específicos ou todos os padrões de URL.

Onde os filtros de servlet são usados?

Os aplicativos da web modernos podem ter dezenas desses filtros. Coisas como autorização, armazenamento em cache, gerenciamento de sessões ORM e injeção de dependência geralmente são implementadas com o auxílio do filtro de servlet. Todos esses filtros precisam ser registrados web.xml.

Instanciando filtros de servlet - sem Spring Framework

Seu contêiner de servlet cria instâncias de Filtros declaradas web.xmle as chama nos horários apropriados (por exemplo, ao atender solicitações de servlet). Agora, se você é como a maioria dos fãs de Injeção de Dependência (DI), provavelmente diria que a criação de instâncias é o que minha estrutura de DI (Spring) faz melhor. Não consigo criar meus filtros de servlet com o Spring para que eles sejam passíveis de todas as vantagens de DI?

DelegatingFilterProxy, para que o Spring crie suas instâncias de filtro

É aqui que as DelegatingFilterProxyetapas. DelegatingFilterProxyÉ uma impelmentação da javax.servlet.Filterinterface fornecida pelo Spring Framework. Depois de configurar o DelegatingFilterProxyweb.xml, você pode declarar os beans reais que fazem a filtragem na sua configuração de primavera. Dessa forma, o Spring cria as instâncias de beans que fazem a filtragem real e você pode usar o DI para configurar esses beans.

Observe que você precisa apenas de uma única DelegatingFilterProxydeclaração, web.xmlmas pode ter vários filtros beanencadeados no contexto do aplicativo.

Tahir Akhtar
fonte
muito bem explicado.
user4906240
15

O problema é que os filtros de servlet são gerenciados pelo contêiner de servlet, e não pela mola. E pode ser necessário injetar alguns componentes da mola em seus filtros.

Então, se você precisar de algo como:

public class FooFilter {

    @Inject
    private FooService service;

    public void doFilter(....) { .. }

}

então você precisa do proxy do filtro de delegação.

Bozho
fonte
1

Você está certo sobre coisas de "cola". Conforme escrito em JavaDocs do FilterChainProxy :

O FilterChainProxy é vinculado à cadeia de filtros do contêiner do servlet, incluindo uma declaração padrão Spring DelegatingFilterProxy no arquivo web.xml do aplicativo.

Consulte a seção FIlterChainProxy do blog Behind the Spring Security Namespace para obter uma excelente explicação.

Ritesh
fonte
0

Fiquei perplexo com "springSecurityFilterChain" em web.xml e encontrei esta resposta no documento de segurança springframework:

O <http>elemento encapsula a configuração de segurança para a camada da web do seu aplicativo. Cria um bean FilterChainProxy chamado "springSecurityFilterChain", que mantém a pilha de filtros de segurança que compõem a configuração de segurança da web [19]. Alguns filtros principais são sempre criados e outros serão adicionados à pilha, dependendo dos atributos filhos que estão presentes. As posições dos filtros padrão são fixas (consulte a tabela de ordem dos filtros na> introdução ao namespace), removendo uma fonte comum de erros nas versões anteriores da estrutura> quando os usuários precisavam configurar a cadeia de filtros explicitamente no beanFilterChainProxy. Obviamente, você ainda pode fazer isso se precisar de controle total da configuração.

Aqui está o link http://docs.spring.io/spring-security/site/docs/3.0.x/reference/appendix-namespace.html

Janet
fonte
0

Já faz muito tempo, mas eu tinha a mesma pergunta e achei o seguinte: https://www.javacodegeeks.com/2013/11/spring-security-behind-the-scenes.html

Tentei executar meu projeto de segurança da primavera removendo o filtro em questão e adicionando-o. O que eu descobri é que se adicionarmos o filtro, somente a chamada será redirecionada para a página de login necessária, conforme definido na configuração de segurança da primavera.

Por isso, concordando com a resposta de @ Ryan.

OutOfMind
fonte