Quel est l'intérêt de DelegatingFilterProxy de Spring MVC?

120

Je vois cela dans mes applications Spring MVC web.xml:

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

J'essaie de comprendre pourquoi c'est là et si c'est vraiment nécessaire.

J'ai trouvé cette explication dans la documentation de Spring mais cela ne m'aide pas à comprendre:

Il semble suggérer que ce composant est le "ciment" entre les servlets définis dans web.xmlet les composants définis dans Spring applicationContext.xml.

7.1 DelegatingFilterProxy

Lorsque vous utilisez des filtres de servlet, vous devez évidemment les déclarer dans votre web.xml, sinon ils seront ignorés par le conteneur de servlet. Dans Spring Security, les classes de filtre sont également des beans Spring définis dans le contexte de l'application et donc capables de tirer parti des riches fonctionnalités d'injection de dépendances et des interfaces de cycle de vie de Spring. Spring's DelegatingFilterProxyfournit le lien entre web.xmlet le contexte de l'application.

Lorsque vous utilisez DelegatingFilterProxy, vous verrez quelque chose comme ceci dans le web.xmlfichier:

<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>

Notez que le filtre est en fait un DelegatingFilterProxy, et non la classe qui implémentera réellement la logique du filtre. Ce qui DelegatingFilterProxyfait est de déléguer les méthodes du filtre à un bean qui est obtenu à partir du contexte d'application Spring. Cela permet au bean de bénéficier de la prise en charge du cycle de vie du contexte de l'application Web Spring et de la flexibilité de configuration. Le bean doit implémenter javax.servlet.Filteret il doit avoir le même nom que celui de l'élément filter-name. Lisez le Javadoc pour DelegatingFilterProxy pour plus d'informations

Donc, si je retire cela de mon web.xml, que va-t-il se passer? Mes servlets ne pourront pas communiquer avec le conteneur Spring? **

Thomas
la source

Réponses:

127

Il y a une sorte de magie ici, mais à la fin, tout est un programme déterministe.

Le DelegatingFilterProxy est un filtre comme il a été expliqué ci - dessus, dont le but est « déléguer à un haricot géré printemps qui implémente l'interface de filtre », qui est, il trouve un haricot ( « haricot cible » ou « délégué ») dans votre application Spring contexte et l’invoque. Comment est-ce possible? Comme ce bean implémente javax.servlet.Filter, sa méthode doFilter est appelée.

Quel haricot s'appelle? le DelegatingFilterProxy "Prend en charge un" targetBeanName "[...], en spécifiant le nom du bean cible dans le contexte d'application Spring."

Comme vous l'avez vu dans votre web.xml, le nom du bean est " springSecurityFilterChain " .

Ainsi, dans le cadre d'une application web, un Filter instancie un bean appelé "springSecurityFilterChain" dans votre contexte d'application puis lui délègue via la méthode doFilter ().

N'oubliez pas que votre contexte d'application est défini avec TOUS LES fichiers CONTEXTE D'APPLICATION (XML). Par exemple: applicationContext.xml ET applicationContext-security.xml.

Essayez donc de trouver un bean appelé "springSecurityFilterChain" dans ce dernier ...

... et probablement vous ne pouvez pas (par exemple si vous avez suivi un tutoriel ou si vous avez configuré la sécurité à l'aide de Roo)

Voici la magie: il y a un nouvel élément pour configurer la sécurité , quelque chose comme

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

comme cela est autorisé par http://www.springframework.org/schema/security/spring-security-3.0.xsd , fera l'affaire.

Lorsque Spring charge le contexte d'application à l'aide de fichiers XML, s'il trouve un élément, il essaiera de configurer la sécurité HTTP, c'est-à-dire une pile de filtres et des URL protégées, et d'enregistrer le FilterChainProxy nommé "springSecurityFilterChain".

Alternativement, vous pouvez définir le bean de manière classique, c'est-à-dire:

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

Mais c'est moins recommandé, car vous devez faire beaucoup de configuration (tous les filtres que vous allez utiliser. Et il y en a plus d'une douzaine)

jbbarquero
la source
"applicationContext-security.xml ET applicationContext-security.xml" est deux fois le même nom de fichier.
musiKk
Merci musiKk (je pense que vous pouvez éditer le message directement)
jbbarquero
C'était l'explication que je cherchais depuis le début et que je clarifiais les choses pour moi.
user871611
@jbbarquero: Vous avez raison mais je ne savais pas quelle devrait être la bonne version. J'ai tendance à laisser cela à l'auteur original de le réparer afin de ne pas changer le sens par inadvertance.
musiKk
D'ACCORD. Dans tous les cas, j'apprécie beaucoup votre aide pour améliorer ma réponse. Merci encore, musiKk
jbbarquero
73

Savez-vous ce qu'est un filtre de servlet et comment il fonctionne? C'est un élément très utile de la spécification de servlet, qui nous permet d'appliquer des concepts de type AOP au service des requêtes HTTP. De nombreux frameworks utilisent des implémentations Filter pour diverses choses, et il n'est pas rare d'en trouver des implémentations personnalisées car elles sont très simples à écrire et utiles. Dans une application Spring, la plupart des choses que votre application peut faire se trouvent dans vos beans Spring. Une instance de filtre, cependant, est contrôlée par le conteneur Servlet. Le conteneur l'instancie, l'initialise et le détruit. Cependant, la spécification de servlet ne nécessite aucun type d'intégration Spring, vous vous retrouvez donc avec un concept vraiment utile (filtres) sans moyen pratique de le lier à votre application Spring et aux beans qui font le travail.

Entrez le DelegatingFilterProxy. Vous écrivez une implémentation de Filter et en faites un bean Spring, mais au lieu d'ajouter votre propre classe Filter au web.xml, vous utilisez DelegatingFilterProxy et lui donnez le nom du bean de votre filtre dans le contexte Spring. (Si vous ne fournissez pas explicitement un nom, il utilise le "nom du filtre".) Ensuite, au moment de l'exécution, DelegatingFilterProxy gère la complexité de trouver la véritable implémentation - celle que vous avez écrite et configurée dans Spring - et d'y acheminer les demandes . Ainsi, au moment de l'exécution, c'est comme si vous aviez répertorié votre filtre dans le fichier web.xml, mais vous bénéficiez de la possibilité de le câbler comme n'importe quel autre Spring bean.

Si vous supprimez ce mappage de filtre de votre web.xml, tout continuera de fonctionner, mais aucune de vos URL ne sera sécurisée. (Cela suppose que le nom «springSecurityFilterChain» décrit précisément ce qu'il fait.) C'est parce que ce mappage filtre chaque requête entrante et la transmet à un filtre de sécurité défini dans votre contexte Spring.

Ryan Stewart
la source
Merci d'avoir publié ce commentaire éclairant. J'apprends maintenant Spring Security, j'essaie de le comprendre suffisamment pour faire des personnalisations. Je n'avais aucune idée de ce qu'étaient les filtres de servlet ou de ce que sont les filtres à ressorts. Votre commentaire sur AOP montre clairement POURQUOI on aurait des filtres au lieu d'utiliser simplement des servlets ........ donc vous n'avez pas à écrire le même pré / post-traitement encore et encore dans chaque servlet / ressource
Steve
Sensationnel. Cette explication est exactement ce dont j'avais besoin. Merci de partager vos connaissances.
Charles Morin
@Ryan Stewart si j'ai deux beans implémente l'interface de filtre dans applicationContext, et que je veux exécuter dans un ordre, alors comment puis-je le faire?
Abhishek Nayak
@skaffman si j'ai deux beans implémente l'interface de filtre dans applicationContext et que je veux exécuter dans un ordre, alors comment puis-je le faire?
Abhishek Nayak
44

Que sont les filtres de servlet?

Les filtres de servlet sont, en général, un concept Java WebApp. Vous pouvez avoir des filtres de servlet dans n'importe quelle application Web, que vous utilisiez ou non le framework Spring dans votre application.

Ces filtres peuvent intercepter les demandes avant qu'elles n'atteignent le servlet cible. Vous pouvez implémenter des fonctionnalités communes, telles que l'autorisation, dans les filtres de servlet. Une fois implémenté, vous pouvez configurer le filtre dans votre web.xml pour qu'il soit appliqué à un servlet spécifique, à des modèles d'URL de demande spécifiques ou à tous les modèles d'URL.

Où les filtres de servlet sont-ils utilisés?

Les applications Web modernes peuvent avoir des dizaines de tels filtres. Des éléments comme l'autorisation, la mise en cache, la gestion de session ORM et l'injection de dépendances sont souvent implémentés à l'aide d'un filtre de servlet. Tous ces filtres doivent être enregistrés dans web.xml.

Instanciation des filtres de servlet - sans Spring Framework

Votre conteneur de servlet crée des instances de Filtres déclarés dans web.xmlet les appelle à des moments appropriés (c'est-à-dire lors du traitement des demandes de servlet). Maintenant, si vous êtes comme la plupart des fans de Dependency Injection (DI), vous diriez probablement que la création d'instances est ce que mon framework DI (Spring) fait mieux. Est-ce que je ne peux pas créer mes filtres de servlet avec Spring pour qu'ils soient compatibles avec toutes les qualités de DI?

DelegatingFilterProxy, afin que Spring crée vos instances de filtre

C'est là qu'intervient DelegatingFilterProxy. DelegatingFilterProxyC'est une impélmentation de l' javax.servlet.Filterinterface fournie par Spring Framework. Une fois que vous avez configuré DelegatingFilterProxydans web.xml, vous pouvez déclarer les beans réels qui effectuent le filtrage dans votre configuration Spring. De cette façon, Spring crée les instances de beans qui effectuent le filtrage réel, et vous pouvez utiliser DI pour configurer ces beans.

Notez que vous n'avez besoin que d'une seule DelegatingFilterProxydéclaration dans web.xmlmais que vous pouvez beanenchaîner plusieurs filtrages dans le contexte de votre application.

Tahir Akhtar
la source
très bien expliqué.
user4906240
15

Le fait est que les filtres de servlet sont gérés par le conteneur de servlet, et non par ressort. Et vous devrez peut-être injecter des composants de ressort dans vos filtres.

Donc, si vous avez besoin de quelque chose comme:

public class FooFilter {

    @Inject
    private FooService service;

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

}

alors vous avez besoin du proxy de filtrage délégant.

Bozho
la source
1

Vous avez raison sur les trucs de «colle». Comme écrit dans JavaDocs de FilterChainProxy :

Le FilterChainProxy est lié à la chaîne de filtres du conteneur de servlet en ajoutant une déclaration Spring DelegatingFilterProxy standard dans le fichier web.xml de l'application.

Veuillez consulter la section FIlterChainProxy du blog Behind the Spring Security Namespace pour une excellente explication.

Ritesh
la source
0

J'ai été perplexe par "springSecurityFilterChain" dans web.xml et j'ai trouvé cette réponse dans le document de sécurité de springframework:

le <http> élément encapsule la configuration de sécurité pour la couche Web de votre application. > Il crée un bean FilterChainProxy nommé "springSecurityFilterChain" qui maintient la pile de> filtres de sécurité qui composent la configuration de sécurité Web [19]. Certains filtres principaux sont toujours> créés et d'autres seront ajoutés à la pile en fonction des éléments enfants des attributs qui sont> présents. Les positions des filtres standard sont fixes (voir le tableau d'ordre des filtres dans> l'introduction de l'espace de noms), supprimant une source commune d'erreurs avec les versions précédentes du framework> lorsque les utilisateurs devaient configurer la chaîne de filtres explicitement dans le beanFilterChainProxy. Vous pouvez, bien sûr, toujours le faire si vous avez besoin d'un contrôle total de la configuration.

Voici le lien http://docs.spring.io/spring-security/site/docs/3.0.x/reference/appendix-namespace.html

Janet
la source
0

Cela faisait longtemps mais j'avais la même question et j'ai trouvé ceci: https://www.javacodegeeks.com/2013/11/spring-security-behind-the-scenes.html

J'ai essayé d'exécuter mon projet de sécurité de ressort en supprimant le filtre en question et aussi en l'ajoutant. Ce que j'ai trouvé, c'est que si nous ajoutons le filtre, alors seulement l'appel sera redirigé vers la page de connexion requise telle que définie dans la configuration de spring-security.

Par conséquent, j'accepte la réponse de @ Ryan.

Hors de l'esprit
la source