Điểm của DelegateFilterProxy của Spring MVC là gì?


120

Tôi thấy điều này trong ứng dụng Spring MVC của mình web.xml:

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

Tôi đang cố gắng tìm hiểu lý do tại sao nó ở đó và liệu nó có thực sự cần thiết hay không.

Tôi đã tìm thấy lời giải thích này trong tài liệu Spring nhưng nó không giúp tôi hiểu được nó:

Có vẻ như gợi ý rằng thành phần này là "keo" giữa các servlet được định nghĩa trong web.xmlvà các thành phần được xác định trong Spring applicationContext.xml.

7.1 Ủy quyềnFilterProxy

Khi sử dụng bộ lọc servlet, bạn rõ ràng cần phải khai báo chúng trong bộ lọc của bạn web.xml, nếu không chúng sẽ bị vùng chứa servlet bỏ qua. Trong Spring Security, các lớp bộ lọc cũng là Spring bean được định nghĩa trong ngữ cảnh ứng dụng và do đó có thể tận dụng các cơ sở phụ thuộc và giao diện vòng đời phong phú của Spring. Spring's DelegatingFilterProxycung cấp liên kết giữa web.xmlvà bối cảnh ứng dụng.

Khi sử dụng DelegateFilterProxy, bạn sẽ thấy một cái gì đó như thế này trong web.xmltệp:

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

Lưu ý rằng bộ lọc thực sự là một DelegatingFilterProxy, và không phải là lớp thực sự sẽ triển khai logic của bộ lọc. Cái gì DelegatingFilterProxylà ủy quyền các phương thức của Bộ lọc cho một bean được lấy từ ngữ cảnh ứng dụng Spring. Điều này cho phép bean hưởng lợi từ hỗ trợ vòng đời ứng dụng web Spring và tính linh hoạt của cấu hình. Bean phải triển khai javax.servlet.Filtervà nó phải có cùng tên với tên trong phần tử tên bộ lọc. Đọc Javadoc cho DelegateFilterProxy để biết thêm thông tin

Vì vậy, nếu tôi lấy nó ra khỏi của tôi web.xml, điều gì sẽ xảy ra? Các Servlet của tôi sẽ không thể giao tiếp với vùng chứa Spring? **

Câu trả lời:


127

Có một số loại ma thuật ở đây, nhưng cuối cùng, mọi thứ đều là một chương trình xác định.

Các DelegatingFilterProxy là một bộ lọc như nó đã được giải thích ở trên, với mục tiêu là " ủy thác cho một Spring bean được quản lý mà cụ giao diện Lọc ", có nghĩa là, nó tìm thấy một bean ( "mục tiêu đậu" hoặc "đại biểu") trong ứng dụng Spring của bạn ngữ cảnh và gọi nó. Làm thế nào là nó có thể? Bởi vì bean này thực hiện javax.servlet.Filter, phương thức doFilter của nó được gọi.

Đậu được gọi là hạt nào? DelegateFilterProxy "Hỗ trợ" targetBeanName "[...], chỉ định tên của bean đích trong ngữ cảnh ứng dụng Spring."

Như bạn đã thấy trong web.xml của mình , tên của bean là " springSecurityFilterChain " .

Vì vậy, trong ngữ cảnh của một ứng dụng web, Bộ lọc khởi tạo một bean có tên "springSecurityFilterChain" trong ngữ cảnh ứng dụng của bạn và sau đó ủy quyền cho nó thông qua phương thức doFilter ().

Hãy nhớ rằng, ngữ cảnh ứng dụng của bạn được xác định với TẤT CẢ CÁC Tệp ỨNG DỤNG-CONTEXT (XML). Ví dụ: applicationContext.xml VÀ applicationContext-security.xml.

Vì vậy, hãy thử tìm một bean có tên "springSecurityFilterChain" trong phần sau ...

... và có thể bạn không thể (ví dụ: nếu bạn đã làm theo hướng dẫn hoặc nếu bạn định cấu hình bảo mật bằng Roo)

Đây là điều kỳ diệu: có một yếu tố mới để định cấu hình bảo mật , giống như

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

vì nó được http://www.springframework.org/schema/security/spring-security-3.0.xsd cho phép , sẽ thực hiện thủ thuật.

Khi Spring tải ngữ cảnh ứng dụng bằng các tệp XML, nếu nó tìm thấy một phần tử, nó sẽ cố gắng thiết lập bảo mật HTTP, nghĩa là, một ngăn xếp bộ lọc và các URL được bảo vệ và đăng ký FilterChainProxy có tên "springSecurityFilterChain".

Ngoài ra, bạn có thể định nghĩa bean theo cách cổ điển, đó là:

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

Nhưng nó ít được khuyến khích hơn, vì bạn cần phải thực hiện nhiều cấu hình (tất cả các bộ lọc mà bạn sẽ sử dụng. Và có hơn một tá bộ lọc trong số đó)


"applicationContext-security.xml VÀ applicationContext-security.xml" là hai tên tệp giống nhau.
musiKk

Cảm ơn musiKk (Tôi nghĩ rằng bạn có thể chỉnh sửa bài trực tiếp)
jbbarquero

Đây là lời giải thích mà tôi đã tìm kiếm tất cả và giải tỏa mọi thứ cho tôi.
user871611

@jbbarquero: Bạn nói đúng nhưng tôi không chắc phiên bản chính xác nên là gì. Tôi có xu hướng để lại điều đó cho tác giả gốc sửa chữa để không vô tình thay đổi ý nghĩa.
musiKk

ĐỒNG Ý. Trong mọi trường hợp, tôi đánh giá cao sự giúp đỡ của bạn để cải thiện phản hồi của tôi. Cảm ơn một lần nữa, musiKk
jbbarquero

73

Bạn có biết Servlet Filter là gì và nó hoạt động như thế nào không? Đó là một phần rất hữu ích của Servlet Spec, cho phép chúng tôi áp dụng các khái niệm giống AOP để phục vụ các yêu cầu HTTP. Nhiều khung công tác sử dụng triển khai Bộ lọc cho nhiều thứ khác nhau và không có gì lạ khi tìm thấy các triển khai tùy chỉnh của chúng vì chúng rất đơn giản để viết và hữu ích. Trong ứng dụng Spring, hầu hết những thứ mà ứng dụng của bạn có thể làm đều nằm trong Spring bean của bạn. Tuy nhiên, một cá thể Bộ lọc được điều khiển bởi vùng chứa Servlet. Vùng chứa khởi tạo, khởi tạo và hủy nó. Mặc dù vậy, Servlet Spec không yêu cầu bất kỳ loại tích hợp Spring nào, vì vậy bạn sẽ bị bỏ lại với một khái niệm thực sự hữu ích (Bộ lọc) mà không có cách nào thuận tiện để liên kết nó với ứng dụng Spring của bạn và các bean thực hiện công việc.

Nhập DelegateFilterProxy. Bạn viết một triển khai Bộ lọc và đặt nó thành một Spring bean, nhưng thay vì thêm lớp Filter của riêng bạn vào web.xml, bạn sử dụng DelegateFilterProxy và đặt cho nó tên bean của bộ lọc của bạn trong ngữ cảnh Spring. (Nếu bạn không cung cấp tên một cách rõ ràng, nó sẽ sử dụng "tên bộ lọc".) Sau đó, trong thời gian chạy, DelegateFilterProxy xử lý sự phức tạp của việc tìm kiếm triển khai thực sự - triển khai bạn đã viết và định cấu hình trong Spring - và định tuyến các yêu cầu tới nó . Vì vậy, trong thời gian chạy, giống như thể bạn đã liệt kê bộ lọc của mình trong web.xml, nhưng bạn nhận được lợi ích là có thể nối dây nó giống như bất kỳ Spring bean nào khác.

Nếu bạn lấy ánh xạ bộ lọc đó ra khỏi web.xml của mình, mọi thứ sẽ tiếp tục hoạt động, nhưng không URL nào của bạn sẽ được bảo mật. (Đó là giả sử tên "springSecurityFilterChain" mô tả chính xác chức năng của nó.) Đó là bởi vì ánh xạ này đang lọc mọi yêu cầu đến và chuyển nó tới một bộ lọc bảo mật được xác định trong ngữ cảnh Spring của bạn.


Cảm ơn vì đã đăng bình luận sáng sủa này. Tôi hiện đang học Spring Security, cố gắng hiểu nó đủ để thực hiện các tùy chỉnh. Tôi không biết bộ lọc servlet là gì hoặc bộ lọc lò xo là gì. Thông tin của bạn về AOP làm rõ TẠI SAO người ta lại có các bộ lọc thay vì chỉ sử dụng các servlet ........ để bạn không phải viết đi viết lại cùng một quá trình xử lý trước / sau trong mỗi servlet / resource
Steve

Chà. Lời giải thích đó là chính xác những gì tôi cần. Cảm ơn vi đa chia sẻ kiên thưc của bạn.
Charles Morin

@Ryan Stewart nếu tôi có hai bean thực hiện Giao diện bộ lọc trong applicationContext và tôi muốn thực thi theo một thứ tự, thì tôi có thể thực hiện nó bằng cách nào?
Abhishek Nayak

@skaffman nếu tôi có hai bean thực hiện Giao diện bộ lọc trong applicationContext và tôi muốn thực thi theo một thứ tự, thì tôi có thể thực hiện nó bằng cách nào?
Abhishek Nayak

44

Bộ lọc Servlet là gì?

Bộ lọc Servlet nói chung là một khái niệm Java WebApp. Bạn có thể có bộ lọc servlet trong bất kỳ ứng dụng web nào, cho dù bạn có sử dụng Spring framework trong ứng dụng của mình hay không.

Các bộ lọc này có thể chặn các yêu cầu trước khi chúng đến được servlet đích. Bạn có thể triển khai chức năng chung, như ủy quyền, trong các bộ lọc servlet. Sau khi được triển khai, bạn có thể định cấu hình bộ lọc trong web.xml của mình để được áp dụng cho một servlet cụ thể, các mẫu url yêu cầu cụ thể hoặc tất cả các mẫu url.

Bộ lọc Servlet được sử dụng ở đâu?

Ứng dụng web hiện đại có thể có hàng tá bộ lọc như vậy. Những thứ như ủy quyền, bộ nhớ đệm, quản lý phiên ORM và chèn phụ thuộc thường được thực hiện với sự hỗ trợ của bộ lọc servlet. Tất cả các bộ lọc này cần phải được đăng ký web.xml.

Khởi tạo bộ lọc Servlet - không có Spring Framework

Vùng chứa servlet của bạn tạo các thể hiện của Bộ lọc được khai báo trong web.xmlvà gọi chúng vào những thời điểm thích hợp (tức là khi cung cấp các yêu cầu servlet). Bây giờ nếu bạn giống như hầu hết những người hâm mộ Dependency Injection (DI), bạn có thể sẽ nói rằng việc tạo ra các phiên bản là những gì mà khung DI của tôi (Spring) làm tốt hơn. Tôi không thể tải các bộ lọc servlet của mình được tạo bằng Spring để chúng có thể đáp ứng được mọi điều tốt đẹp của DI?

DelegatingFilterProxy, để Spring tạo các bản sao bộ lọc của bạn

Đây là nơi mà DelegatingFilterProxycác bước trong. DelegatingFilterProxyLà sự thúc đẩy của javax.servlet.Filtergiao diện được cung cấp bởi Spring Framework. Khi bạn định cấu hình DelegatingFilterProxytrong web.xml, bạn có thể khai báo các bean thực sự thực hiện việc lọc trong cấu hình mùa xuân của bạn. Bằng cách này, Spring tạo các phiên bản của bean thực hiện quá trình lọc thực tế và bạn có thể sử dụng DI để cấu hình các bean này.

Lưu ý rằng bạn chỉ cần một DelegatingFilterProxykhai báo duy nhất web.xmlnhưng bạn có thể có nhiều beanchuỗi lọc được xâu chuỗi lại với nhau trong ngữ cảnh ứng dụng của bạn.


giải thích rất tốt.
user4906240

15

Vấn đề là, các bộ lọc servlet được quản lý bởi thùng chứa servlet chứ không phải bởi mùa xuân. Và bạn có thể cần phải đưa một số thành phần lò xo vào bộ lọc của mình.

Vì vậy, nếu bạn cần một cái gì đó như:

public class FooFilter {

    @Inject
    private FooService service;

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

}

thì bạn cần proxy bộ lọc ủy quyền.


1

Bạn nói đúng về công cụ 'keo'. Như được viết trong JavaDocs của FilterChainProxy :

FilterChainProxy được liên kết vào chuỗi bộ lọc vùng chứa servlet bằng cách thêm khai báo Spring DelegateFilterProxy tiêu chuẩn trong tệp web.xml ứng dụng.

Vui lòng xem phần FIlterChainProxy của blog Phía sau không gian tên bảo mật mùa xuân để có lời giải thích tuyệt vời.


0

Tôi đã bối rối bởi "springSecurityFilterChain" trong web.xml và tìm thấy câu trả lời này trong tài liệu bảo mật springframework:

Phần <http>tử đóng gói cấu hình bảo mật cho lớp web của ứng dụng của bạn. > Nó tạo ra một bean FilterChainProxy có tên là "springSecurityFilterChain" để duy trì ngăn xếp> bộ lọc bảo mật tạo nên cấu hình bảo mật web [19]. Một số bộ lọc lõi luôn được tạo> và những bộ lọc khác sẽ được thêm vào ngăn xếp tùy thuộc vào các phần tử con thuộc tính> hiện tại. Vị trí của các bộ lọc tiêu chuẩn được cố định (xem bảng thứ tự bộ lọc trong> giới thiệu không gian tên), loại bỏ nguồn lỗi phổ biến với các phiên bản trước của khuôn khổ> khi người dùng phải định cấu hình chuỗi bộ lọc rõ ràng trong bean FilterChainProxy. Tất nhiên, bạn vẫn có thể làm điều này nếu bạn cần toàn quyền kiểm soát cấu hình.

Đây là liên kết http://docs.spring.io/spring-security/site/docs/3.0.x/reference/append-namespace.html


0

Đã lâu rồi nhưng tôi có cùng một câu hỏi và tôi tìm thấy điều này: https://www.javacodegeeks.com/2013/11/spring-security-behind-the-scenes.html

Tôi đã cố gắng chạy dự án bảo mật mùa xuân của mình bằng cách xóa bộ lọc được đề cập và cũng bằng cách thêm nó. Những gì tôi tìm thấy là nếu chúng tôi thêm bộ lọc, chỉ khi đó cuộc gọi sẽ chuyển hướng đến trang đăng nhập bắt buộc như được xác định trong cấu hình bảo mật mùa xuân.

Do đó, đồng ý với câu trả lời của @ Ryan.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.