स्प्रिंग सुरक्षा फ़िल्टर श्रृंखला एक बहुत ही जटिल और लचीला इंजन है।
श्रृंखला में मुख्य फिल्टर (क्रम में) हैं
- SecurityContextPersistenceFilter (JSESSIONID से प्रमाणीकरण पुनर्स्थापित करता है)
- UsernamePasswordAuthenticationFilter (प्रमाणीकरण करता है)
- ExceptionTranslationFilter (FilterSecurityInterceptor से सुरक्षा अपवादों को पकड़ें)
- FilterSecurityInterceptor (प्रमाणीकरण और प्राधिकरण अपवादों को फेंक सकता है)
को देखते हुए वर्तमान स्थिर रिलीज 4.2.1 प्रलेखन , खंड 13.3 फ़िल्टर आदेश आप पूरे फिल्टर श्रृंखला के फिल्टर संगठन देख सकते हैं:
13.3 फ़िल्टर ऑर्डर करना
फ़िल्टर में जो क्रम परिभाषित किया गया है वह बहुत महत्वपूर्ण है। चाहे जो भी फ़िल्टर आप वास्तव में उपयोग कर रहे हों, क्रम इस प्रकार होना चाहिए:
ChannelProcessingFilter , क्योंकि इसे एक अलग प्रोटोकॉल पर पुनर्निर्देशित करना पड़ सकता है
SecurityContextPersistenceFilter , इसलिए एक SecurityContext को एक वेब अनुरोध के प्रारंभ में SecurityContextHolder में सेट किया जा सकता है, और SecurityContext में किसी भी परिवर्तन को HttpSession में कॉपी किया जा सकता है जब वेब अनुरोध समाप्त होता है (अगले वेब अनुरोध के साथ उपयोग के लिए तैयार)
ConcurrentSessionFilter , क्योंकि यह SecurityContextHolder कार्यक्षमता का उपयोग करता है और प्रमुख से चल रहे अनुरोधों को प्रतिबिंबित करने के लिए SessionRegistry को अपडेट करने की आवश्यकता है।
प्रमाणीकरण प्रसंस्करण तंत्र -
UsernamePasswordAuthenticationFilter , CasAuthenticationFilter ,
BasicAuthenticationFilter आदि - ताकि SecurityContextHolder को एक वैध प्रमाणीकरण अनुरोध टोकन शामिल करने के लिए संशोधित किया जा सके
SecurityContextHolderAwareRequestFilter , आप अपने सर्वलेट कंटेनर में एक स्प्रिंग सुरक्षा के बारे में पता HttpServletRequestWrapper स्थापित करने के लिए यह प्रयोग कर रहे हैं
JaasApiIntegrationFilter , अगर एक JaasAuthenticationToken SecurityContextHolder में है इस JaasAuthenticationToken में विषय के रूप में FilterChain पर कार्रवाई करेंगे
याद रखेंमैंथिकेशनफिल्टर , ताकि यदि कोई पहले प्रमाणीकरण प्रसंस्करण तंत्र ने SecurityContextHolder को अपडेट नहीं किया है, और अनुरोध एक कुकी प्रस्तुत करता है जो याद रखने वाली सेवाओं को लेने में सक्षम बनाता है, एक उपयुक्त याद किया गया प्रमाणीकरण ऑब्जेक्ट वहां रखा जाएगा।
AnonymousAuthenticationFilter , ताकि यदि कोई पहले प्रमाणीकरण संसाधन तंत्र ने SecurityContextHolder को अपडेट नहीं किया है, तो एक अनाम प्रमाणीकरण ऑब्जेक्ट को वहां रखा जाएगा
ExceptionTranslationFilter , किसी भी स्प्रिंग सुरक्षा अपवाद को पकड़ने के लिए ताकि या तो एक HTTP त्रुटि प्रतिक्रिया वापस आ सके या एक उपयुक्त AuthenticationEntryPoint लॉन्च किया जा सके
FilterSecurityInterceptor , वेब URI की सुरक्षा के लिए और पहुँच से वंचित होने पर अपवादों को बढ़ाने के लिए
अब, मैं आपके प्रश्नों को एक-एक करके आगे बढ़ाने का प्रयास करूँगा:
मुझे भ्रम है कि इन फ़िल्टर का उपयोग कैसे किया जाता है क्या यह है कि स्प्रिंग को फ़ॉर्म-लॉगिन प्रदान किया गया है, UsernamePasswordAuthenticationFilter केवल / लॉगिन के लिए उपयोग किया जाता है, और बाद वाले फ़िल्टर नहीं हैं? क्या प्रपत्र-लॉगिन नामस्थान तत्व इन फ़िल्टर को स्वतः कॉन्फ़िगर करता है? क्या हर अनुरोध (प्रमाणित या नहीं) गैर-लॉगिन यूआरएल के लिए FilterSecurityInterceptor तक पहुंचता है?
एक बार जब आप एक <security-http>
अनुभाग को कॉन्फ़िगर कर रहे हैं , तो प्रत्येक के लिए आपको कम से कम एक प्रमाणीकरण तंत्र प्रदान करना होगा। यह उन फ़िल्टरों में से एक होना चाहिए जो स्प्रिंग सिक्योरिटी डॉक्यूमेंटेशन के 13.3 फ़िल्टर ऑर्डरिंग सेक्शन में समूह 4 से मेल खाते हैं, जिसका मैंने अभी संदर्भ लिया है।
यह न्यूनतम वैध सुरक्षा है: http तत्व जिसे कॉन्फ़िगर किया जा सकता है:
<security:http authentication-manager-ref="mainAuthenticationManager"
entry-point-ref="serviceAccessDeniedHandler">
<security:intercept-url pattern="/sectest/zone1/**" access="hasRole('ROLE_ADMIN')"/>
</security:http>
बस कर, ये फ़िल्टर फ़िल्टर श्रृंखला प्रॉक्सी में कॉन्फ़िगर किए गए हैं:
{
"1": "org.springframework.security.web.context.SecurityContextPersistenceFilter",
"2": "org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter",
"3": "org.springframework.security.web.header.HeaderWriterFilter",
"4": "org.springframework.security.web.csrf.CsrfFilter",
"5": "org.springframework.security.web.savedrequest.RequestCacheAwareFilter",
"6": "org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter",
"7": "org.springframework.security.web.authentication.AnonymousAuthenticationFilter",
"8": "org.springframework.security.web.session.SessionManagementFilter",
"9": "org.springframework.security.web.access.ExceptionTranslationFilter",
"10": "org.springframework.security.web.access.intercept.FilterSecurityInterceptor"
}
नोट: मैं उन्हें एक साधारण RestController बनाकर प्राप्त करता हूं जो @Autowires FilterChainProxy और रिटर्न यह सामग्री है:
@Autowired
private FilterChainProxy filterChainProxy;
@Override
@RequestMapping("/filterChain")
public @ResponseBody Map<Integer, Map<Integer, String>> getSecurityFilterChainProxy(){
return this.getSecurityFilterChainProxy();
}
public Map<Integer, Map<Integer, String>> getSecurityFilterChainProxy(){
Map<Integer, Map<Integer, String>> filterChains= new HashMap<Integer, Map<Integer, String>>();
int i = 1;
for(SecurityFilterChain secfc : this.filterChainProxy.getFilterChains()){
//filters.put(i++, secfc.getClass().getName());
Map<Integer, String> filters = new HashMap<Integer, String>();
int j = 1;
for(Filter filter : secfc.getFilters()){
filters.put(j++, filter.getClass().getName());
}
filterChains.put(i++, filters);
}
return filterChains;
}
यहाँ हम देख सकते हैं कि केवल <security:http>
एक न्यूनतम विन्यास के साथ तत्व की घोषणा करके , सभी डिफ़ॉल्ट फ़िल्टर शामिल हैं, लेकिन उनमें से कोई भी एक प्रमाणीकरण प्रकार का नहीं है (13.3 फ़िल्टर ऑर्डरिंग अनुभाग में चौथा समूह)। तो यह वास्तव में इसका मतलब है कि सिर्फ security:http
तत्व की घोषणा करके , SecurityContextPersistenceFilter, ExceptionTranslationFilter और FilterSecurityInterceptor ऑटो-कॉन्फ़िगर हैं।
वास्तव में, एक प्रमाणीकरण प्रसंस्करण तंत्र को कॉन्फ़िगर किया जाना चाहिए, और यहां तक कि सुरक्षा नामस्थान सेम प्रसंस्करण के दावे भी, जो स्टार्टअप के दौरान एक त्रुटि फेंकते हैं, लेकिन इसे प्रविष्टि-बिंदु-रेफरी विशेषता को जोड़कर बाईपास किया जा सकता है। <http:security>
यदि मैं <form-login>
कॉन्फ़िगरेशन में एक मूल जोड़ देता हूं , तो इस तरह से:
<security:http authentication-manager-ref="mainAuthenticationManager">
<security:intercept-url pattern="/sectest/zone1/**" access="hasRole('ROLE_ADMIN')"/>
<security:form-login />
</security:http>
अब, फ़िल्टरचैन इस तरह होगा:
{
"1": "org.springframework.security.web.context.SecurityContextPersistenceFilter",
"2": "org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter",
"3": "org.springframework.security.web.header.HeaderWriterFilter",
"4": "org.springframework.security.web.csrf.CsrfFilter",
"5": "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter",
"6": "org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter",
"7": "org.springframework.security.web.savedrequest.RequestCacheAwareFilter",
"8": "org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter",
"9": "org.springframework.security.web.authentication.AnonymousAuthenticationFilter",
"10": "org.springframework.security.web.session.SessionManagementFilter",
"11": "org.springframework.security.web.access.ExceptionTranslationFilter",
"12": "org.springframework.security.web.access.intercept.FilterSecurityInterceptor"
}
अब, यह दो फिल्टर org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter और org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter बनाया है और FilterChainProxy में विन्यस्त कर रहे हैं।
तो, अब, सवाल:
क्या यह है कि स्प्रिंग को फ़ॉर्म-लॉगिन प्रदान किया गया है, UsernamePasswordAuthenticationFilter केवल / लॉगिन के लिए उपयोग किया जाता है, और बाद वाले फ़िल्टर नहीं हैं?
हां, यह उपयोगकर्ता नामपासवर्ड ऑथेंटिकेशनफिल्टर यूआरएल से मेल खाने के मामले में लॉगिन प्रोसेसिंग तंत्र को पूरा करने की कोशिश करने के लिए उपयोग किया जाता है। इस url को कॉन्फ़िगर किया जा सकता है या यहां तक कि इसे बदला जा सकता है यह प्रत्येक अनुरोध से मेल खाने के लिए व्यवहार है।
आपके पास एक से अधिक प्रमाणीकरण प्रसंस्करण तंत्र एक ही FilterchainProxy (जैसे HttpBasic, CAS, आदि) में कॉन्फ़िगर हो सकते हैं।
क्या प्रपत्र-लॉगिन नामस्थान तत्व इन फ़िल्टर को स्वतः कॉन्फ़िगर करता है?
नहीं, प्रपत्र लॉगिन तत्व UsernamePasswordAUthenticationFilter को कॉन्फ़िगर करता है, और अगर आप लॉगिन-पृष्ठ url प्रदान नहीं करते हैं, तो यह org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter को भी कॉन्फ़िगर करता है, जो एक साधारण ऑटोजर में समाप्त होता है। पृष्ठ।
अन्य फ़िल्टर <security:http>
बिना किसी security:"none"
विशेषता के एक तत्व बनाकर डिफ़ॉल्ट रूप से स्वतः कॉन्फ़िगर किए जाते हैं ।
क्या हर अनुरोध (प्रमाणित या नहीं) गैर-लॉगिन यूआरएल के लिए FilterSecurityInterceptor तक पहुंचता है?
प्रत्येक अनुरोध को उस तक पहुंचना चाहिए, क्योंकि यह वह तत्व है जो इस बात का ध्यान रखता है कि अनुरोध के पास अनुरोधित यूआरएल तक पहुंचने के अधिकार हैं या नहीं। लेकिन फ़िल्टर से पहले संसाधित किए गए कुछ फ़िल्टर केवल कॉल नहीं करने वाले फ़िल्टर श्रृंखला प्रसंस्करण को रोक सकते हैं FilterChain.doFilter(request, response);
। उदाहरण के लिए, CSRF फ़िल्टर फ़िल्टर श्रृंखला प्रसंस्करण को रोक सकता है यदि अनुरोध में csrf पैरामीटर नहीं है।
क्या होगा यदि मैं JWT- टोकन के साथ अपने REST API को सुरक्षित करना चाहता हूं, जिसे लॉगिन से पुनर्प्राप्त किया गया है? मुझे दो नामस्थान कॉन्फ़िगरेशन http टैग, अधिकारों को कॉन्फ़िगर करना होगा? अन्य एक / लॉगिन के साथ UsernamePasswordAuthenticationFilter
, और कस्टम के साथ REST url के लिए एक अन्य JwtAuthenticationFilter
।
नहीं, आप इस तरह से करने के लिए मजबूर नहीं हैं। आप एक ही http तत्व में UsernamePasswordAuthenticationFilter
और दोनों को घोषित कर सकते हैं JwtAuthenticationFilter
, लेकिन यह इस फिल्टर के प्रत्येक के ठोस व्यवहार पर निर्भर करता है। दोनों दृष्टिकोण संभव हैं, और जो एक को चुनना है वह स्वयं की प्राथमिकताओं पर निर्भर करता है।
क्या दो http तत्वों को कॉन्फ़िगर करने से दो स्प्रिंग सिक्योरिटीफिटलरचिन बनते हैं?
हाँ यह सच है
जब तक मैं फ़ॉर्म-लॉगिन घोषित नहीं करता, तब तक UsernamePasswordAuthenticationFilter डिफ़ॉल्ट रूप से बंद हो जाता है?
हां, आप इसे मेरे द्वारा पोस्ट किए गए सभी कॉन्फ़िगरेशन में उठाए गए फ़िल्टर में देख सकते हैं
मैं SecurityContextPersistenceFilter को एक के साथ कैसे बदलूं, जो JSESSIONID के बजाय मौजूदा JWT- टोकन से प्रमाणीकरण प्राप्त करेगा?
आप SecurityContextPersistenceFilter से बच सकते हैं, बस सत्र की रणनीति को कॉन्फ़िगर कर सकते हैं <http:element>
। बस इस तरह कॉन्फ़िगर करें:
<security:http create-session="stateless" >
या, इस मामले में आप इसे एक अन्य फ़िल्टर के साथ अधिलेखित कर सकते हैं, इस तरह से <security:http>
तत्व के अंदर :
<security:http ...>
<security:custom-filter ref="myCustomFilter" position="SECURITY_CONTEXT_FILTER"/>
</security:http>
<beans:bean id="myCustomFilter" class="com.xyz.myFilter" />
संपादित करें:
"आप एक ही फ़िल्टरचैनप्रॉक्सी में कॉन्फ़िगर किए गए एक से अधिक प्रमाणीकरण प्रसंस्करण तंत्र हो सकते हैं" के बारे में एक प्रश्न। यदि पहले (एक से अधिक कार्यान्वयन) प्रमाणीकरण फिल्टर की घोषणा करते हैं, तो क्या उत्तरार्द्ध पहले एक द्वारा किए गए प्रमाणीकरण को अधिलेखित करेगा? यह कैसे कई प्रमाणीकरण प्रदाताओं से संबंधित है?
यह अंततः प्रत्येक फ़िल्टर के कार्यान्वयन पर निर्भर करता है, लेकिन यह सच है कि बाद के प्रमाणीकरण फ़िल्टर कम से कम पूर्ववर्ती फ़िल्टर द्वारा किए गए किसी भी पूर्व प्रमाणीकरण को अधिलेखित करने में सक्षम हैं।
लेकिन ऐसा नहीं होगा। मेरे पास सुरक्षित आरईएसटी सेवाओं में कुछ उत्पादन के मामले हैं जहां मैं एक तरह के प्राधिकरण टोकन का उपयोग करता हूं जिसे एचटीपी के हेडर के रूप में या अनुरोध निकाय के अंदर दोनों प्रदान किया जा सकता है। इसलिए मैं दो फिल्टर कॉन्फ़िगर करता हूं जो उस टोकन को पुनर्प्राप्त करता है, एक मामले में एचटीटीपी हेडर से और दूसरा खुद के बाकी अनुरोध के अनुरोध निकाय से। यह सच है कि अगर एक http अनुरोध उस प्रमाणीकरण टोकन को Http हैडर के रूप में और अनुरोध निकाय के अंदर दोनों प्रदान करता है, तो दोनों फ़िल्टर प्रबंधक को यह बताते हुए प्रमाणीकरण तंत्र को निष्पादित करने का प्रयास करेंगे, लेकिन अनुरोध को जाँचने पर इसे आसानी से टाला जा सकता है। पहले से ही प्रमाणित doFilter()
प्रत्येक फिल्टर की विधि की शुरुआत पर ।
एक से अधिक प्रमाणीकरण फ़िल्टर होना एक से अधिक प्रमाणीकरण प्रदाताओं से संबंधित है, लेकिन इसे बाध्य न करें। मेरे द्वारा पहले उजागर किए गए मामले में, मेरे पास दो प्रमाणीकरण फ़िल्टर हैं, लेकिन मेरे पास केवल एक प्रमाणीकरण प्रदाता है, क्योंकि दोनों फ़िल्टर एक ही प्रकार के प्रमाणीकरण ऑब्जेक्ट बनाते हैं, इसलिए दोनों स्थितियों में प्रमाणीकरण प्रबंधक इसे एक ही प्रदाता को सौंपता है।
और इसके विपरीत, मेरे पास एक परिदृश्य भी है जहां मैं सिर्फ एक उपयोगकर्ता नाम प्रकाशित करता हूंअस्पष्ट संकेत फ़ाइटर लेकिन उपयोगकर्ता क्रेडेंशियल्स दोनों डीबी या एलडीएपी में निहित हो सकते हैं, इसलिए मेरे पास दो उपयोगकर्ता नामपसंदीदाताउपयोगकर्ताओकेन सहायक प्रदाता हैं, और प्रमाणीकरण प्रदाता से फ़िल्टर करने के लिए किसी भी प्रमाणीकरण प्रयास को प्रमाणित करता है। जानबूझकर साख को मान्य करने के लिए।
इसलिए, मुझे लगता है कि यह स्पष्ट है कि न तो प्रमाणीकरण फ़िल्टर प्रमाणीकरणकर्ताओं की मात्रा निर्धारित करते हैं और न ही प्रदाता फ़िल्टर की मात्रा निर्धारित करते हैं।
इसके अलावा, प्रलेखन में कहा गया है कि SecurityContextPersistenceFilter SecurityContext की सफाई के लिए जिम्मेदार है, जो थ्रेड पूलिंग के कारण महत्वपूर्ण है। यदि मैं इसे छोड़ देता हूं या कस्टम कार्यान्वयन प्रदान करता हूं, तो मुझे मैन्युअल रूप से सफाई को लागू करना होगा, है ना? चेन को कस्टमाइज़ करते समय क्या ऐसे ही मिलते हैं?
मैंने पहले इस फ़िल्टर को ध्यान से नहीं देखा था, लेकिन आपके अंतिम प्रश्न के बाद मैं इसे लागू कर रहा हूँ और आमतौर पर वसंत में, लगभग सब कुछ कॉन्फ़िगर किया जा सकता है, विस्तारित या अधिलेखित किया जा सकता है।
SecurityContextPersistenceFilter एक में प्रतिनिधियों SecurityContextRepository कार्यान्वयन SecurityContext के लिए खोज। डिफ़ॉल्ट रूप से, एक HttpSessionSecurityContextRepository का उपयोग किया जाता है, लेकिन फ़िल्टर के किसी एक निर्माता का उपयोग करके इसे बदला जा सकता है। तो एक SecurityContextRepository लिखना बेहतर हो सकता है जो आपकी आवश्यकताओं को पूरा करता है और इसे SecurityContextPersistenceFilter में कॉन्फ़िगर करता है, इस पर विश्वास करते हुए कि यह खरोंच से सभी बनाने के बजाय व्यवहार को साबित करता है।