क्या मैं <url-pattern> के अंदर <फिल्टर-मैपिंग> से कुछ ठोस यूआरएल निकाल सकता हूं?


127

मैं चाहता हूं कि एक ठोस (यानी को /*छोड़कर /specialpath) को छोड़कर सभी url के लिए कुछ ठोस फ़िल्टर लागू किया जाए ।

क्या ऐसा करने की संभावना है?


नमूना कोड:

<filter>
    <filter-name>SomeFilter</filter-name>
    <filter-class>org.somproject.AFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SomeFilter</filter-name>
    <url-pattern>/*</url-pattern>   <!-- the question is: how to modify this line?  -->
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

जवाबों:


156

मानक सर्वलेट एपीआई इस सुविधा का समर्थन नहीं करता है। आप या तो इसके लिए टर्की के एक (जो कि काफी हद तक अपाचे एचटीडी के समान है mod_rewrite) के लिए एक रीराइट-यूआरएल फिल्टर का उपयोग कर सकते हैं , या doFilter()फ़िल्टर सुनने की विधि में एक चेक जोड़ सकते हैं /*

String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
    chain.doFilter(request, response); // Just continue chain.
} else {
    // Do your business stuff here for all paths other than /specialpath.
}

यदि आवश्यक हो तो आप init-paramफ़िल्टर के रूप में पथ-से-अनदेखा निर्दिष्ट कर सकते हैं ताकि आप इसे web.xmlवैसे भी नियंत्रित कर सकें । आप इसे निम्नानुसार फ़िल्टर में प्राप्त कर सकते हैं:

private String pathToBeIgnored;

public void init(FilterConfig config) {
    pathToBeIgnored = config.getInitParameter("pathToBeIgnored");
}

यदि फ़िल्टर 3rd पार्टी एपीआई का हिस्सा है और इस प्रकार आप इसे संशोधित नहीं कर सकते हैं, तो इसे और अधिक विशिष्ट पर मैप करें url-pattern, उदाहरण के लिए /otherfilterpath/*और एक नया फ़िल्टर बनाएं , /*जिस पर आगे चलकर 3rd पार्टी फ़िल्टर से मेल खाता है।

String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
    chain.doFilter(request, response); // Just continue chain.
} else {
    request.getRequestDispatcher("/otherfilterpath" + path).forward(request, response);
}

इससे बचने के लिए कि यह फ़िल्टर आपको एक अनंत लूप में बुलाएगा, जिसे आपको REQUESTकेवल और केवल 3 पार्टी फिल्टर पर सुनने (भेजने) की आवश्यकता होगी FORWARD

यह सभी देखें:


3
मेरी समस्या यह है कि फिल्टर मेरा नहीं है, यह घटक पुस्तकालय से है।
रोमन

4
Ypu को अपवर्जित लाइब्रेरी फ़िल्टर लेना चाहिए और इसे एक्सक्लूसिव करने के लिए उपयोग किए जाने वाले कोड को जोड़ने के लिए विस्तारित करना चाहिए।
gbtimmon

@BalusC यदि "/ स्पेशलपैथ" सिर्फ एक स्थिर संसाधन जैसे js, css इत्यादि की सेवा करता है, तो क्या chain.doFilter () प्रतिक्रिया धीमी करता है? क्या फिल्टर का पीछा किए बिना सीधे संसाधन की सेवा करने की एक विधि है?
बेन्हुर्सीडी

@ बन्हुरसीडी: मुझे वास्तव में कोई पता नहीं है कि आप इस प्रदर्शन की चिंता में कैसे आ सकते हैं।
बालूसी

13

मैंने एरिक डॉटरटी द्वारा वर्णित दृष्टिकोण का उपयोग किया : मैंने एक विशेष सर्वलेट बनाया, जो हमेशा 403 कोड के साथ उत्तर देता है और इसकी मैपिंग सामान्य से पहले करता है।

मैपिंग टुकड़ा:

  <servlet>
    <servlet-name>generalServlet</servlet-name>
    <servlet-class>project.servlet.GeneralServlet</servlet-class>
  </servlet>
 <servlet>
    <servlet-name>specialServlet</servlet-name>
    <servlet-class>project.servlet.SpecialServlet</servlet-class>
 </servlet>
 <servlet-mapping>
    <servlet-name>specialServlet</servlet-name>
    <url-pattern>/resources/restricted/*</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
    <servlet-name>generalServlet</servlet-name>
    <url-pattern>/resources/*</url-pattern>
 </servlet-mapping>

और सर्वलेट क्लास:

public class SpecialServlet extends HttpServlet {
    public SpecialServlet() {
        super();
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.sendError(HttpServletResponse.SC_FORBIDDEN);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.sendError(HttpServletResponse.SC_FORBIDDEN);
    }
}

9

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

डिफ़ॉल्ट सर्वलेट के लिए अपने स्थिर संसाधन फ़ाइलों के साथ फ़ोल्डर को मैप करें। एक सर्वलेट फ़िल्टर बनाएं और इसे अपने web.xml में GuiceFilter के सामने रखें। आपके द्वारा बनाए गए फ़िल्टर में, आप कुछ अनुरोधों को अग्रेषित करने के लिए अलग कर सकते हैं GuiceFilter और दूसरों को सीधे डिस्पैचर में। उदाहरण इस प्रकार है ...

web.xml

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>StaticResourceFilter</filter-name>
    <filter-class>com.project.filter.StaticResourceFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>StaticResourceFilter</filter-name>
    <url-pattern>/static/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

StaticResourceFilter.class

public class StaticResourceFilter implements Filter {

    private final static Logger LOGGER = LoggerFactory.getLogger(StaticResourceFilter.class);

    private static final String RESOURCE_PATH = "/static/";
    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
        LOGGER.info("StaticResourceFilter initialized");
    }

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response,
                         final FilterChain chain) throws IOException, ServletException {

        String path = ((HttpServletRequest) request).getServletPath();
        if (path.toLowerCase().startsWith(RESOURCE_PATH)) {
            request.getRequestDispatcher(path).forward(request, response);
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
        LOGGER.info("StaticResourceFilter destroyed");
    }
}

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


मैंने आपके समाधान के साथ जाने की कोशिश की, लेकिन उन फ़ाइलों के लिए जिन्हें मैं फ़िल्टर लागू करता हूं और श्रृंखला को तोड़ता हूं, मुझे फॉलोइन त्रुटि मिलती है; फ़िल्टर स्टेटिक रिसोर्स फ़िल्टर द्वारा फेंका गया अपवाद नहीं छोड़ा गया: java.io.FileNotFoundException। कोई विचार क्यों?
शामली

बहु-संदर्भ सेटअप में, उपयोग करने .getRequestURI()से टूट जाएगा (404 सबसे अधिक संभावना है) क्योंकि संदर्भ पथ के सापेक्ष.getRequestDispatcher हल होता है । यदि आपका संदर्भ पथ है /a, तो आपके उदाहरण में अनुरोध URI होगा /a/static, और इसका उपयोग getRequestDispatcher("/a/static")करने के /a/a/staticबजाय इसके विरुद्ध समाधान होगा। फिक्स: के .getServletPath()बजाय का उपयोग करें .getRequestURI()। मैं इसे ठीक करने के लिए एक संपादन प्रस्तुत करूँगा, लेकिन मैं एक टिप्पणी छोड़ना चाहता था FYI करें
रीड

3

मुझे नहीं लगता कि आप कर सकते हैं, केवल अन्य कॉन्फ़िगरेशन विकल्प उन रास्तों की गणना करना है जिन्हें आप फ़िल्टर्ड करना चाहते हैं, इसलिए इसके बजाय /*आप कुछ के लिए /this/*और /that/*आदि जोड़ सकते हैं , लेकिन जब आपके पास एक बहुत बड़ा समाधान नहीं होगा उन रास्तों से।

आप जो कर सकते हैं वह फ़िल्टर को एक पैरामीटर जोड़कर एक अभिव्यक्ति प्रदान करता है (एक नियमित अभिव्यक्ति की तरह) जो कि मिलान किए गए रास्तों के लिए फ़िल्टर कार्यक्षमता को छोड़ने के लिए उपयोग किया जाता है। सर्वलेट कंटेनर अभी भी उन url के लिए आपके फ़िल्टर को कॉल करेगा, लेकिन आपके पास कॉन्फ़िगरेशन पर बेहतर नियंत्रण होगा।

संपादित करें

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

एक डेलिगेटिंग फिल्टर (एक आवरण) के निर्माण का लाभ यह है कि आप लिपटे फिल्टर के फ़िल्टर वर्ग को पैरामीटर के रूप में जोड़ सकते हैं और इसे इस तरह की अन्य स्थितियों में पुन: उपयोग कर सकते हैं।


3

मुझे जावा कोड में URL पैटर्न (/ {servicename} / api / आँकड़े /) के आधार पर फ़िल्टर करना पड़ा।

if (path.startsWith("/{servicename}/api/statistics/")) {
validatingAuthToken(((HttpServletRequest) request).getHeader("auth_token"));
filterChain.doFilter(request, response);            
}

लेकिन इसका विचित्र, वह सर्वलेट url पैटर्न के अलावा (/ *) का समर्थन नहीं करता है, यह सर्वलेट एपीआई के लिए एक बहुत ही सामान्य मामला होना चाहिए!


0

मैंने एक ही मुद्दे का सामना किया है, लेकिन मुझे नीचे दी गई एक अन्वेषक दिखाई दे रही है।

web.xml

 <!-- set this param value for the filter-->
    <init-param>
            <param-name>freePages</param-name>
            <param-value>
            MainFrame.jsp;
            </param-value>
    </init-param>

filter.java

strFreePages = config.getInitParameter("freePages"); //get the exclue pattern from config file
isFreePage(strRequestPage)  //decide the exclude path

इस तरह से आपको कंक्रीट फ़िल्टर क्लास को परेशान नहीं करना पड़ेगा।


0

यदि किसी भी कारण से आप मेरे मामले में मूल फ़िल्टर मैपिंग ("/ *") को नहीं बदल सकते हैं और आप किसी अपरिवर्तनीय तृतीय-पक्ष फ़िल्टर को भेज रहे हैं, तो आप निम्न उपयोगी पा सकते हैं:

  • बाईपास किए जाने वाले मार्ग को बाधित करें
  • फ़िल्टर श्रृंखला के अंतिम रिंग को छोड़ें और निष्पादित करें (स्वयं सर्वलेट)
  • लंघन को प्रतिबिंब के माध्यम से किया जाता है, डिबग मोड में कंटेनर के उदाहरणों का निरीक्षण किया जाता है

वेबलॉजिक में निम्नलिखित कार्य 12.1.3:

      import org.apache.commons.lang3.reflect.FieldUtils;
      import javax.servlet.Filter;

      [...]

      @Override   
      public void doFilter(ServletRequest request, ServletRespons response, FilterChain chain) throws IOException, ServletException { 
          String path = ((HttpServletRequest) request).getRequestURI();

          if(!bypassSWA(path)){
              swpFilterHandler.doFilter(request, response, chain);

          } else {
              try {
                  ((Filter) (FieldUtils.readField(
                                (FieldUtils.readField(
                                        (FieldUtils.readField(chain, "filters", true)), "last", true)), "item", true)))
                  .doFilter(request, response, chain);
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              }           
          }   
      }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.