2012-11-26 12 views
14

हम वसंत एमवीसी + वसंत सुरक्षा + हाइबरनेट के साथ एक विश्वसनीय API बना रहे हैं। एपीआई जेएसओएन और एचटीएमएल दोनों का उत्पादन कर सकता है। वसंत सुरक्षा के लिए एक अच्छी त्रुटि हैंडलिंग करना मुझे सिरदर्द दे रहा है:वसंत सुरक्षा में कस्टम अपवादों को संभालें

प्रमाणीकरण विभिन्न तरीकों से हो सकता है: मूल अनुरोध, POST अनुरोध में विभिन्न पैरामीटर के माध्यम से और वेब लॉग-इन के माध्यम से भी। प्रत्येक प्रमाणीकरण तंत्र के लिए, वसंत सुरक्षा xml कॉन्फ़िगरेशन के <http> नेमस्पेस तत्व में घोषित एक फ़िल्टर है।

हम अपने सभी वसंत अपवादों को कस्टम HandlerExceptionResolver में संभालते हैं। यह हमारे नियंत्रकों में फेंकने वाले सभी अपवादों के लिए ठीक काम करता है, लेकिन मुझे नहीं पता कि कस्टम वसंत सुरक्षा फ़िल्टर में फेंकने वाले कस्टम अपवादों को कैसे संभाला जाए। चूंकि वसंत सुरक्षा फ़िल्टर हमारे किसी भी नियंत्रक के आने से पहले आता है, इसलिए हमें अपवाद नहीं दिखते हैं कि हम अपने कस्टम वसंत सुरक्षा फ़िल्टर में फेंक देते हैं।

मुझे यह प्रश्न यहां stackoverflow पर मिला: Use custom exceptions in Spring Security। हालांकि मुझे नहीं पता कि वे वहां फेंकने वाले अपवादों को कैसे संभालते हैं। हमने इस दृष्टिकोण की कोशिश की लेकिन हमारे कस्टम HandlerExceptionResolver को नहीं कहा जाता है। इसके बजाए उपयोगकर्ता को टॉमकैट द्वारा प्रस्तुत एक बदसूरत स्टैकट्रस के साथ प्रस्तुत किया जाता है।

हमें इसकी आवश्यकता क्यों है? उपयोगकर्ताओं को सक्रिय और निष्क्रिय किया जा सकता है। यदि वे निष्क्रिय हैं और कुछ क्रियाएं करने का प्रयास करते हैं तो हम एक कस्टम त्रुटि संदेश के साथ जेएसओएन वापस करना चाहते हैं। वसंत सुरक्षा AccessDeniedException फेंकने पर यह प्रदर्शित होने से अलग होना चाहिए। AccessDeniedException किसी भी तरह से यह हमारे HandlerExceptionResolver पर बनाता है, लेकिन मैं वास्तव में कैसे पालन नहीं कर सका।

संभव समाधान हम एक ExceptionTranslationFilter का उपयोग कर के बारे में सोचा है, लेकिन इस नहीं बुलाया जाता है जब हम अपने कस्टम अपवाद (विधि doFilter() की पकड़ बयान में एक ब्रेकपाइंट सेट) फेंक देते हैं। मेरी समझ में इस पकड़ ब्लॉक को बुलाया जाना चाहिए और प्रमाणीकरण प्रविष्टि बिंदु का उपयोग किया जाना चाहिए।

एक और संभावना है: हम वसंत सुरक्षा फिल्टर श्रृंखला में ExceptionTranslationFilter के लिए इसी तरह कुछ करना है और क्या इसके AccessDeniedHandler करता है के लिए इसी तरह कुछ कर सकते हैं:

RequestDispatcher dispatcher = request.getRequestDispatcher(errorPage); 
dispatcher.forward(request, response); 

हम कुछ पैरामीटर जोड़ सकता है (त्रुटि कोड, कारण आदि) अनुरोध के लिए और यह एक नियंत्रक को इंगित करता है जो JSON या HTML में प्रतिपादन का ख्याल रखेगा।

स्प्रिंग सुरक्षा::

यहाँ हमारे विन्यास की एक छोटी अंश है

<http create-session="stateless" use-expressions="true" > 
    <!-- Try getting the authorization object from the request parameters. --> 
    <security:custom-filter ref="filter1" after="SECURITY_CONTEXT_FILTER"/> 
    <security:custom-filter ref="filter2" before="LOGOUT_FILTER"/> 
    <!-- Intercept certain URLS differently --> 

    <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" /> 
    <!-- Some more stuff here --> 
    <intercept-url pattern="/**" access="denyAll" /> 
    <http-basic /> 
</http> 

HandlerExceptionResolver

@Bean 
public HandlerExceptionResolver handlerExceptionResolver(){ 
    logger.info("creating handler exception resolver"); 
    return new AllExceptionHandler(); 
} 

हमारे कस्टम HandlerExceptionResolver की AppConfig

public class AllExceptionHandler implements HandlerExceptionResolver { 

    private static final Logger logger = LoggerFactory 
     .getLogger(AppConfig.class); 

    @Override 
    public ModelAndView resolveException(HttpServletRequest request, 
      HttpServletResponse response, Object handler, Exception ex) { 
    // This is just a snipped of the real method code 
    return new ModelAndView("errorPage"); 
} 

हमारे फ़िल्टर में से एक के प्रासंगिक भाग:

try { 
    Authentication authResult = authenticationManger.authenticate(authRequest); 
    SecurityContextHolder.getContext().setAuthentication(authResult); 
} 

catch(AuthenticationException failed) { 
    SecurityContextHolder.clearContext(); 
    throw failed; 
} 

web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 
<context-param> 
    <param-name>contextClass</param-name> 
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> 
</context-param> 
<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>xxx.xxx.xxx.config</param-value> 
</context-param> 
<context-param> 
    <param-name>spring.profiles.default</param-name> 
    <param-value>LIVE</param-value> 
</context-param> 
<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 
<servlet> 
    <servlet-name>appServlet</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value></param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
    <!-- Add multipart support for files up to 10 MB --> 
    <multipart-config> 
     <max-file-size>10000000</max-file-size> 
    </multipart-config> 
</servlet> 
<servlet-mapping> 
    <servlet-name>appServlet</servlet-name> 
    <url-pattern>/</url-pattern> 
</servlet-mapping> 
<filter> 
    <filter-name>openEntityManagerInViewFilter</filter-name> 
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>openEntityManagerInViewFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 
<filter> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 
<!-- Map filters --> 
<filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 
<error-page> 
    <error-code>404</error-code> 
    <location>/handle/404</location> 
</error-page> 
</web-app> 

किसी को भी हम यह कैसे हल कर सकते थे पर किसी भी संकेत दिए गए है? मैंने Google पर कई लेखों को देखा, उनमें से अधिकतर वर्णन करते हैं कि वसंत सुरक्षा द्वारा फेंक दिया गया AccessDeniedException को कैसे संभालना है जब कोई फ़िल्टर अनुरोध प्रमाणित करने में सक्षम नहीं होता है।

हम वसंत सुरक्षा 3.1.0 और वसंत वेब एमवीसी 3.1.0 का उपयोग कर रहे हैं।

उत्तर

8

यह याद रखना महत्वपूर्ण है कि वसंत सुरक्षा मामलों में फ़िल्टर का क्रम महत्वपूर्ण है।

Spring Security 3 किताब से

:

ExceptionTranslationFilter संभालने के लिए और को केवल उन अपवादों कि फिल्टर श्रृंखला निष्पादन ढेर में यह नीचे फेंक दिया जाता है प्रतिक्रिया करने के लिए सक्षम हो जाएगा। उपयोगकर्ता अक्सर भ्रमित हो जाते हैं, खासकर जब गलत फ़िल्टर में कस्टम फ़िल्टर जोड़ते हैं, तो क्यों अपेक्षित व्यवहार उनके अनुप्रयोग के वास्तविक अपवाद हैंडलिंग से अलग है- में से कई मामलों में, फ़िल्टर का क्रम दोष देना है!

यदि आपके फ़िल्टर प्राधिकरण के बारे में हैं तो उन्हें श्रृंखला का अंत रखने का एक अच्छा अभ्यास है क्योंकि इस दृष्टिकोण का उपयोग डिफ़ॉल्ट प्राधिकरण फ़िल्टर द्वारा किया जाता है। इस तरह आपको पहिया को फिर से शुरू करने की ज़रूरत नहीं है।

स्टैंडर्ड फिल्टर: Table in documentation

के बाद आप ठीक ढंग से अपने फिल्टर श्रृंखला के लिए कॉन्फ़िगर, तो आपको त्रुटि पेज, या यहाँ तक कि कस्टम हैंडलर कॉन्फ़िगर कर सकते हैं। अधिक जानकारी documentation में उपलब्ध है।

+1

आपके उत्तर के लिए धन्यवाद: बस यह सुनिश्चित करने के लिए कि अगर मैं आपको सही तरीके से समझता हूं। आप मेरे फ़िल्टर के लिए = "EXCEPTION_TRANSLATION_FILTER" के बाद कुछ का उपयोग करने का सुझाव देते हैं। – David

+0

हां। 'EXCEPTION_TRANSLATION_FILTER' के बाद कोई भी स्थिति अच्छी है। –

+0

यह एक कस्टम हैंडलर के साथ संयोजन में चाल करेगा। धन्यवाद! – David

0

मुझे लगता है कि अपवाद ट्रांस्लेशन फ़िल्टर केवल दो अपवादों को संभालता है प्रमाणीकरण अपवाद और AccessDeniedException इन दो अपवादों के लिए कस्टम हैंडलर के साथ, किसी अन्य प्रकार के अपवाद या यहां तक ​​कि रन अप अपवादों के बारे में क्या है?

स्प्रिंग फ़िल्टर स्टैक में किसी भी अपवाद के बारे में आप कैसे हस्तक्षेप/अवरोध करेंगे? पकड़ने और अनुरोध पाने के लिए कोई वसंत मानक तरीका नहीं है (सबकुछ के ऊपर एक कस्टम फ़िल्टर लिखने के अलावा), सबकुछ के ऊपर एक और फ़िल्टर लिखने के बिना प्रतिक्रिया?

<security:http auto-config="false" use-expressions="true" 
disable-url-rewriting="true" entry-point-ref="authenticationEntryPoint" 
pattern="/**"> 

<security:custom-filter before="FIRST" ref="stackExceptionFilter" /> 

<security:custom-filter before="..." ref="authenticationFilter" /> 
<security:logout /> 
</security:http> 

ठीक है, मैं सही शीर्ष पर एक और फिल्टर जोड़ने समाप्त हो गया (या फ़िल्टर कॉन्फ़िगर के लिए/* web.xml में) कि बस कैच ब्लॉक की कोशिश की थी और बुला एक कस्टम अपवाद संचालक वसंत घटक के लिए किसी भी न आया हुआ अपवाद प्रत्यायोजित एक अपवाद प्रकार (हमारी आवश्यकता) के आधार पर एक अपवाद नियंत्रक विधि (अलग-अलग तरीकों से अलग-अलग प्रतिक्रिया प्रकार को लौटने वाली प्रत्येक विधि) एक असफल सुरक्षित तरीके से कस्टम अपवाद संदेश भी लौटाती है। एकमात्र नीचे हिस्सा कुछ तर्क जोड़ना था ताकि आप लूपिंग नहीं रख सकें। स्प्रिंग कस्टम अपवाद हैंडलरएक्सप्शन रीसोलवर और @ एक्सेप्शन हैंडलर नियंत्रकों में फ़िल्टर अपवादों को संभाल नहीं लेते हैं और इस पर सीमा है कि आप अपवाद संदेश को कैसे वापस करना चाहते हैं (एक्सएमएल/जेएसओएन, रीडायरेक्ट, फॉरवर्ड, ....)। यह मानता है कि आपके पास अच्छा एप्लीकेशन अपवाद पदानुक्रम है जो अपवादों को पकड़ता है और उन्हें समझदार संदर्भ जानकारी के साथ फेंकता है क्योंकि फ़िल्टर में कुछ भी नहीं है।

त्रुटि कोड के लिए समान, वेब.एक्सएमएल में स्थिर पृष्ठों को परिभाषित करें, लेकिन त्रुटि कोड को प्रदर्शित करने वाले पृष्ठों के लिए मॉडल तैयार करने और उन्हें फ़िल्टर कोड को मैप करके उन्हें पकड़ें।

संबंधित मुद्दे