2012-09-19 14 views
5

द्वारा संरक्षित है, मेरे पास एक JSF पृष्ठ है जो j_security_check द्वारा संरक्षित नहीं है। मैं निम्नलिखित चरणों का पालन करता हूं:ViewExpiredException AJAX अनुरोध पर नहीं फेंक दिया गया है यदि JSF पृष्ठ j_security_check

  1. ब्राउज़र में जेएसएफ पृष्ठ खोलें।
  2. सर्वर को पुनरारंभ करें।
  3. AJAX कॉल शुरू करने के लिए जेएसएफ पृष्ठ पर कमांड बटन पर क्लिक करें।

फायरबग से पता चलता है कि ViewExpiredException अपेक्षित के रूप में उठाया गया है।

पोस्ट:

javax.faces.ViewState=8887124636062606698:-1513851009188353364 

प्रतिक्रिया:

<partial-response> 
<error> 
<error-name>class javax.faces.application.ViewExpiredException</error-name> 
<error-message>viewId:/viewer.xhtml - View /viewer.xhtml could not be restored.</error-message> 
</error> 
</partial-response> 

हालांकि, (मेरे लिए एक बार मैं j_security_check द्वारा संरक्षित और इसके बाद के संस्करण, अजीब दिए गए उन्हीं चरणों को पूरा किए जाने की पेज कॉन्फ़िगर) ViewExpiredException अब उठाया नहीं गया है। इसके बजाय, प्रतिवाद सिर्फ एक नया दृश्य राज्य है।

पोस्ट:

javax.faces.ViewState=-4873187770744721574:8069938124611303615 

प्रतिक्रिया:

<partial-response> 
<changes> 
<update id="javax.faces.ViewState">234065619769382809:-4498953143834600826</update> 
</changes> 
</partial-response> 

किसी की मदद कर सकते हैं मुझे यह पता लगा? मैं उम्मीद करता हूं कि यह अपवाद उठाए ताकि मैं उस अपवाद को संसाधित कर सकूं और एक त्रुटि पृष्ठ दिखा सकूं। अब यह सिर्फ एक नया व्यूस्टेट के साथ प्रतिक्रिया करता है, मेरा पृष्ठ किसी भी दृश्य प्रतिक्रिया के बिना अटक गया है।

उत्तर

7

मैं आपकी समस्या को पुन: उत्पन्न करने में सक्षम था। यहां क्या हो रहा है कि कंटेनर RequestDispatcher#forward() को लॉगिन पृष्ठ पर सुरक्षा बाधा में निर्दिष्ट करता है। हालांकि, यदि लॉगिन पृष्ठ स्वयं एक जेएसएफ पृष्ठ भी है, तो FacesServlet अग्रेषित अनुरोध पर भी लागू किया जाएगा। चूंकि अनुरोध आगे है, यह केवल अग्रेषित संसाधन (लॉगिन पृष्ठ) पर एक नया दृश्य बनाएगा। हालांकि, चूंकि यह अजाक्स अनुरोध है और render जानकारी नहीं है (संपूर्ण पोस्ट अनुरोध मूल रूप से सुरक्षा जांच के दौरान त्याग दिया जाता है), केवल दृश्य स्थिति वापस कर दी जाएगी।

ध्यान दें कि यदि लॉगिन पृष्ठ जेएसएफ पृष्ठ (जैसे जेएसपी या सादा एचटीएमएल) नहीं था, तो AJAX अनुरोध पृष्ठ के पूरे HTML आउटपुट को AJAX प्रतिक्रिया के रूप में वापस कर देता था जो जेएसएफ AJAX द्वारा अचूक है और " खाली "प्रतिक्रिया।

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

आप इस प्रकार एक PhaseListener के रूप में के साथ इस लक्ष्य को हासिल कर सकते हैं:

public class AjaxLoginListener implements PhaseListener { 

    @Override 
    public PhaseId getPhaseId() { 
     return PhaseId.RESTORE_VIEW; 
    } 

    @Override 
    public void beforePhase(PhaseEvent event) { 
     // NOOP. 
    } 

    @Override 
    public void afterPhase(PhaseEvent event) { 
     FacesContext context = event.getFacesContext(); 
     HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest(); 
     String originalURL = (String) request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI); 
     String loginURL = request.getContextPath() + "/login.xhtml"; 

     if (context.getPartialViewContext().isAjaxRequest() 
      && originalURL != null 
      && loginURL.equals(request.getRequestURI())) 
     { 
      try { 
       context.getExternalContext().invalidateSession(); 
       context.getExternalContext().redirect(originalURL); 
      } catch (IOException e) { 
       throw new FacesException(e); 
      } 
     } 
    } 
} 

अद्यतन इस समाधान OmniFaces 1.2 के बाद से OmniPartialViewContext में बनाया गया है। तो यदि आप पहले से ही OmniFaces का उपयोग करते हैं, तो यह समस्या fully transparently हल हो गई है और इसके लिए आपको कस्टम PhaseListener की आवश्यकता नहीं है।

+0

धन्यवाद बलससी। मेरा दिन बचाया –

+0

आपका स्वागत है। – BalusC

+0

ओह एक अतिरिक्त सवाल, मैं सोच रहा हूं कि निम्नलिखित क्यों होता है: यदि मैं context.getExternalContext() का उपयोग करता हूं। रीडायरेक्ट (loginURL), यह वास्तव में मुझे लॉगिन पेज पर रीडायरेक्ट करता है। लेकिन लॉग इन करने के बाद, एक एक्सएमएल फ़ाइल, व्यूस्टेट के साथ इसकी सामग्री के रूप में, ब्राउज़र द्वारा प्रदर्शित की जाती है। एक्सएमएल फ़ाइल मेरे प्रश्न में पोस्ट की गई दूसरी एक्सएमएल फ़ाइल के समान ही है। अगर मैं context.getExternalContext() का उपयोग करता हूं। रीडायरेक्ट (homepageURL), सभी ठीक काम करता है। यह मुझे लॉगिन पेज ले जाएगा। लॉग इन करने के बाद, होम पेज प्रदर्शित किया जाएगा। –

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