JQuery Ajax कॉल के बाद पुनर्निर्देशित अनुरोध को कैसे प्रबंधित करें


1368

मैं $.post()Ajax का उपयोग करके एक सर्वलेट कॉल करने के लिए उपयोग कर रहा हूं और फिर divउपयोगकर्ता के वर्तमान पृष्ठ में एक तत्व को बदलने के लिए परिणामी HTML टुकड़े का उपयोग कर रहा हूं । हालाँकि, यदि सत्र समय समाप्त हो जाता है, तो सर्वर उपयोगकर्ता को लॉगिन पृष्ठ पर भेजने के लिए एक पुनर्निर्देशन निर्देश भेजता है। इस मामले में, jQuery divलॉगिन पृष्ठ की सामग्री के साथ तत्व की जगह ले रहा है , जो उपयोगकर्ता की आँखों को वास्तव में एक दुर्लभ दृश्य देखने के लिए मजबूर करता है।

मैं jQuery 1.2.6 के साथ अजाक्स कॉल से पुनर्निर्देशित निर्देश कैसे प्रबंधित कर सकता हूं?


1
(इस तरह के रूप में एक जवाब नहीं) - मैंने अतीत में jquery लाइब्रेरी को संपादित करके और प्रत्येक XHR पूर्ण पर लॉगिन पृष्ठ के लिए एक चेक जोड़कर किया है। सबसे अच्छा समाधान नहीं है क्योंकि इसे हर बार अपग्रेड करते समय करना होगा, लेकिन यह समस्या को हल करता है।
सुगेन्द्रन

1
संबंधित प्रश्न देखें: stackoverflow.com/questions/5941933/…
नटाल

HttpContext.Response.AddHeaderAjaxsetup सफलता पर और चेक जाने का रास्ता है
LCJ

4
क्यों सर्वर 401 को वापस नहीं कर सकता? उस स्थिति में आपके पास एक वैश्विक $ .ajaxSetup हो सकता है और पेज को पुनर्निर्देशित करने के लिए स्थिति कोड का उपयोग कर सकता है।
विशाल

1
यह लिंक doanduyhai.wordpress.com/2012/04/21/… मुझे सही समाधान देता है
pappu_kutty

जवाबों:


697

मैंने इस प्रश्न को पढ़ा और उस दृष्टिकोण को लागू किया, जो प्रतिक्रिया HTTP स्थिति कोड को 278 तक सेट करने के संबंध में कहा गया है ताकि ब्राउज़र को पारदर्शी रूप से रीडायरेक्ट से निपटने से बचा जा सके। हालांकि यह काम कर रहा था, मैं थोड़ा असंतुष्ट था क्योंकि यह एक हैक का एक सा है।

अधिक खुदाई के बाद, मैंने इस दृष्टिकोण को खोद लिया और JSON का उपयोग किया । इस स्थिति में, AJAX अनुरोधों की सभी प्रतिक्रियाओं में स्थिति कोड 200 होता है और प्रतिक्रिया के मुख्य भाग में JSON ऑब्जेक्ट होता है जो सर्वर पर निर्मित होता है। क्लाइंट पर जावास्क्रिप्ट तब JSON ऑब्जेक्ट का उपयोग करके यह तय कर सकता है कि उसे क्या करने की आवश्यकता है।

मुझे भी आपकी ऐसी ही समस्या थी। मैं एक AJAX अनुरोध करता हूं जिसमें 2 संभावित प्रतिक्रियाएं हैं: एक जो ब्राउज़र को एक नए पृष्ठ पर पुनर्निर्देशित करता है और एक जो वर्तमान पृष्ठ पर मौजूदा HTML फॉर्म को नए के साथ बदलता है । ऐसा करने के लिए jQuery कोड कुछ इस तरह दिखता है:

$.ajax({
    type: "POST",
    url: reqUrl,
    data: reqBody,
    dataType: "json",
    success: function(data, textStatus) {
        if (data.redirect) {
            // data.redirect contains the string URL to redirect to
            window.location.href = data.redirect;
        } else {
            // data.form contains the HTML for the replacement form
            $("#myform").replaceWith(data.form);
        }
    }
});

JSON ऑब्जेक्ट "डेटा" का निर्माण सर्वर पर 2 सदस्यों के लिए किया जाता है: data.redirectऔर data.form। मुझे यह तरीका बहुत बेहतर लगा।


58
जैसा कि stackoverflow.com/questions/503093/… में समाधान में कहा गया है। window.location.replace (data.redirect) का उपयोग करना बेहतर है; window.location.href = data.redirect की तुलना में;
कार्ल्स बैरोब्स

8
किसी भी कारण से यह कार्रवाई पर HTTP कोड का उपयोग करना बेहतर नहीं होगा। उदाहरण के लिए एक 307 कोड जो HTTP अस्थायी पुनर्निर्देशन है?
सर्गेई गोलोस

15
@ शेर्गी गोलोस इसका कारण है कि यदि आप एक HTTP रीडायरेक्ट करते हैं, तो रीडायरेक्ट वास्तव में कभी भी अजाक्स कॉलबैक में नहीं आता है। ब्राउजर रीडायरेक्ट के गंतव्य के कंटेंट के साथ 200 कोड डिलीवर करने की प्रक्रिया करता है।
मिगुएल सिल्वा

2
सर्वर कोड कैसा दिखेगा? data.form और data.redirect का रिटर्न मान है। मूल रूप से मैं कैसे निर्धारित करूँ कि मैं इसमें पुनर्निर्देशित करूँ?
वेंज

6
यह उत्तर अधिक उपयोगी होगा यदि यह दिखाया गया था कि सर्वर पर यह कैसे किया जाता है।
पेड्रो होहल कारवाल्हो

243

मैंने इस समस्या को हल किया:

  1. प्रतिक्रिया में एक कस्टम हेडर जोड़ना:

    public ActionResult Index(){
        if (!HttpContext.User.Identity.IsAuthenticated)
        {
            HttpContext.Response.AddHeader("REQUIRES_AUTH","1");
        }
        return View();
    }
  2. ajaxSuccessईवेंट में जावास्क्रिप्ट फ़ंक्शन को बांधना और यह देखने के लिए जांचें कि क्या हेडर मौजूद है:

    $(document).ajaxSuccess(function(event, request, settings) {
        if (request.getResponseHeader('REQUIRES_AUTH') === '1') {
           window.location = '/';
        }
    });

6
क्या कमाल का उपाय है। मुझे वन-स्टॉप समाधान का विचार पसंद है। मुझे 403 स्थिति की जांच करने की आवश्यकता है, लेकिन मैं इसके लिए बॉडी पर अजाक्ससुइट बाइंड का उपयोग कर सकता हूं (जो कि मैं वास्तव में देख रहा था।) धन्यवाद।
ब्रेटिकस

4
मैंने बस यही किया और पाया कि मुझे ajaxComplete की आवश्यकता है जहां मैं $ .get () फ़ंक्शन का उपयोग कर रहा था और 200 के अलावा कोई भी स्थिति फायरिंग नहीं कर रही थी। वास्तव में, मैं इसके बजाय शायद ajaxError के लिए बाध्य हो सकता है। अधिक जानकारी के लिए नीचे मेरा उत्तर देखें।
ब्रेटिकस

2
यह कई मामलों में ठीक है, लेकिन अगर आपकी रूपरेखा प्राधिकरण को संभालती है तो क्या होगा?
ज्वालाजीको

13
मुझे हेडर दृष्टिकोण पसंद है लेकिन यह भी लगता है - जैसे @ mwoods79 - कि जहां से रीडायरेक्ट करने के लिए ज्ञान का डुप्लिकेट नहीं होना चाहिए। मैंने बूलियन के बजाय एक शीर्ष लेख REDIRECT_LOCATION जोड़कर हल किया।
रिंतिस

3
रीडायरेक्ट को रीडायरेक्ट पर हेडर सेट करने के लिए ध्यान रखें। जैसा कि इस पृष्ठ पर अन्य उत्तरों में वर्णित है, पुनर्निर्देशन ajaxSucces हैंडलर के लिए पारदर्शी हो सकता है। इस प्रकार मैंने लॉगिन पेज के जीईटी प्रतिक्रिया पर हेडर को शामिल किया (जो अंततः और केवल मेरे परिदृश्य में ajaxSuccess को ट्रिगर करता है)।
sieppl

118

कोई भी ब्राउज़र 301 और 302 प्रतिक्रियाओं को सही तरीके से नहीं संभालता है। और वास्तव में मानक यहां तक ​​कि कहते हैं कि उन्हें "पारदर्शी रूप से" संभालना चाहिए जो कि अजाक्स लाइब्रेरी विक्रेताओं के लिए एक व्यापक सिरदर्द है। में रा-अजाक्स हम पारदर्शी रूप से संभाल करने के लिए सर्वर से पुनर्निर्देश HTTP प्रतिक्रिया स्थिति कोड 278 (सिर्फ कुछ "अप्रयुक्त" सफलता कोड) का उपयोग करने के लिए मजबूर किया गया ...

यह वास्तव में मुझे गुस्सा दिलाता है, और अगर यहाँ किसी को W3C में कुछ "खींच" है, तो मैं सराहना करूँगा कि आप W3C को बता सकते हैं कि हमें वास्तव में 301 और 302 कोड खुद को संभालने की आवश्यकता है ...! ;)


3
मुझे लगता है कि 278 आधिकारिक HTTP युक्ति से अलग हो जाना चाहिए।
क्रिस मैरीसिक

2
क्या यह पहले से ही उन्हें पारदर्शी रूप से नहीं संभालता है? यदि कोई संसाधन स्थानांतरित हो गया है, तो इसे पारदर्शी रूप से संभालने का अर्थ है प्रदान किए गए URL पर अनुरोध को दोहराना। मैं XMLHttpRequest API का उपयोग करने की अपेक्षा करता हूं।
फिलिप राथे

@ फिलिपेथे सहमत। पारदर्शी रूप से संभालना सिर्फ मैं चाहता हूं। और मुझे नहीं पता कि इसे बुरा क्यों माना जाता है।
smwikipedia

@smwikipedia पृष्ठ के पुनर्निर्देशन के बिना मुख्य अनुभाग में मार्कअप के पुनर्निर्देशन की व्यवस्था करना।
cmc

अगर यहाँ किसी के पास W3C में कुछ "पुल" है, तो मैं सराहना करूँगा कि आप W3C को यह बता सकते हैं कि हमें वास्तव में 301 और 302 कोड खुद को संभालने की आवश्यकता है ...! ;)
टॉमी.टंग

100

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

उदाहरण के लिए, हमारा रैपर फंक्शन कुछ इस तरह था:

function cbWrapper(data, funct){
    if($("#myForm", data).length > 0)
        top.location.href="login.htm";//redirection
    else
        funct(data);
}

फिर, अजाक्स कॉल करते समय हमने कुछ इस तरह का उपयोग किया:

$.post("myAjaxHandler", 
       {
        param1: foo,
        param2: bar
       },
       function(data){
           cbWrapper(data, myActualCB);
       }, 
       "html"
);

यह हमारे लिए काम करता है क्योंकि सभी Ajax कॉल हमेशा HTML को एक DIV तत्व के अंदर लौटाते हैं जिसका उपयोग हम पृष्ठ के एक टुकड़े को बदलने के लिए करते हैं। साथ ही, हमें केवल लॉगिन पृष्ठ पर पुनर्निर्देशित करना होगा।


4
ध्यान दें कि इसे cbWrapper (फंक्शनल) {रिटर्न फंक्शन (डेटा) {if ($ ("# myForm", डेटा) फंक्शन को छोटा किया जा सकता है। size ()> 0) top.location.href = "लॉगिन"; अन्य कार्यात्मक (डेटा); }}। जब कॉल करते हैं तो आपको केवल cbWrapper (myActualCB) की आवश्यकता होती है। हां, टिप्पणियों में कोड एक गड़बड़ है लेकिन इसे नोट किया जाना चाहिए :)
सिमेन एच्होल्ट 18'10

आकार का मूल्यह्रास किया जाता है, इसलिए आप इसका उपयोग कर सकते हैं। यहां आकार के स्थान पर गति करें
सुनील

66

मुझे नींबू के एक मामूली मोड़ के साथ टिमरज़ की विधि पसंद है। अगर तुम कभी लौट आओ JSON की उम्मीद करते समय पाठ / html की सामग्री टाइप करते हैं , तो आप सबसे अधिक पुनर्निर्देशित होने की संभावना रखते हैं। मेरे मामले में, मैं बस पृष्ठ को पुनः लोड करता हूं, और यह लॉगिन पृष्ठ पर पुनर्निर्देशित हो जाता है। ओह, और जांचें कि jqXHR स्थिति 200 है, जो मूर्खतापूर्ण लगती है, क्योंकि आप त्रुटि फ़ंक्शन में हैं, है ना? अन्यथा, वैध त्रुटि के मामले पुनरावृत्ति लोड (उफ़) के लिए मजबूर करेंगे

$.ajax(
   error:  function (jqXHR, timeout, message) {
    var contentType = jqXHR.getResponseHeader("Content-Type");
    if (jqXHR.status === 200 && contentType.toLowerCase().indexOf("text/html") >= 0) {
        // assume that our login has expired - reload our current page
        window.location.reload();
    }

});

1
बहुत बहुत धन्यवाद ब्रायन, आपका उत्तर मेरे परिदृश्य के लिए सबसे अच्छा था, हालाँकि मैं चाहूंगा कि अगर कोई सुरक्षित जाँच हो जैसे कि url / पेज सरल "कंटेंट-टाइप" चेक के बजाय रीडायरेक्ट हो रहा है। मुझे पता नहीं चल पाया कि कौन सा पेज jqXHR ऑब्जेक्ट से रीडायरेक्ट हो रहा है।
जॉनी

मैंने स्थिति 401 के लिए जाँच की और फिर पुनर्निर्देशित किया। चंवर की तरह काम करता है।
एरिक

55

निम्न-स्तरीय $.ajax()कॉल का उपयोग करें:

$.ajax({
  url: "/yourservlet",
  data: { },
  complete: function(xmlHttp) {
    // xmlHttp is a XMLHttpRquest object
    alert(xmlHttp.status);
  }
});

इसे पुनर्निर्देशित करने के लिए प्रयास करें:

if (xmlHttp.code != 200) {
  top.location.href = '/some/other/page';
}

मैं निम्न स्तर के सामान से बचने की कोशिश कर रहा था। वैसे भी, मान लीजिए कि मैं आपके द्वारा वर्णित किसी चीज का उपयोग करता हूं, एक बार जब मैं पता लगाता हूं कि HTTP कोड 3xx है तो मैं एक ब्राउज़र पुनर्निर्देशन को कैसे मजबूर करूं? मेरा लक्ष्य उपयोगकर्ता को पुनर्निर्देशित करना है, न कि केवल यह घोषणा करना कि उसका सत्र समाप्त हो गया है।
इलियट वर्गास

4
Btw, $ .ajax () बहुत कम नहीं है, बहुत कम-स्तर। यह jQuery के संदर्भ में केवल निम्न-स्तर है क्योंकि $ .get, $ .post, आदि हैं जो $ .ajax और उसके सभी विकल्पों की तुलना में बहुत अधिक सरल हैं।
तक

16
ओह यार! क्षमा करें, मुझे आपका उत्तर "अन-एक्सेप्ट" करना पड़ा, यह अभी भी बहुत मददगार है। बात यह है, पुनर्निर्देशन स्वतः ही XMLHttpRequest द्वारा प्रबंधित किया जाता है, इसलिए मुझे हमेशा पुनर्निर्देशन (आह!) के बाद 200 स्थिति कोड मिलता है। मुझे लगता है कि मुझे HTML को पार्स करने और मार्कर की तलाश करने जैसा कुछ बुरा करना होगा।
इलियट वर्गास

1
बस उत्सुक, अगर सत्र सर्वर पर समाप्त होता है, तो क्या इसका मतलब यह नहीं है कि सर्वर एक अलग SESSIONID भेजता है? क्या हम सिर्फ उसका पता नहीं लगा सकते थे?
सलामन्डर २०० Sal

10
नोट: यह रीडायरेक्ट के लिए काम नहीं करता है। ajax नए पेज पर जाएगा और अपना स्टेटस कोड लौटाएगा।

33

मैं सिर्फ अपना दृष्टिकोण साझा करना चाहता था क्योंकि यह किसी की मदद कर सकता है:

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

मेरा परिदृश्य: हमारे पास मूल रूप से एक ISA सर्वर है जिसके बीच में सभी अनुरोधों को सुनता है और हमारे लॉगिन पृष्ठ पर 302 और एक स्थान हेडर के साथ प्रतिक्रिया करता है

मेरे जावास्क्रिप्ट मॉड्यूल में मेरा प्रारंभिक दृष्टिकोण कुछ ऐसा था

$(document).ajaxComplete(function(e, xhr, settings){
    if(xhr.status === 302){
        //check for location header and redirect...
    }
});

समस्या (जैसा कि यहां पहले ही उल्लेख किया गया है) यह है कि ब्राउज़र अपने आप ही रीडायरेक्ट को संभालता है, जहां से मेरे ajaxCompleteकॉलबैक को कभी कॉल नहीं किया जाता है, लेकिन इसके बजाय मुझे पहले से रीडायरेक्ट किए गए लॉगिन पेज की प्रतिक्रिया मिली, जो स्पष्ट रूप से एक थीstatus 200 । समस्या: आप कैसे पता लगा सकते हैं कि सफल 200 प्रतिसाद आपका वास्तविक लॉगिन पृष्ठ है या केवल कुछ अन्य मनमाना पृष्ठ है ??

समाधान

चूंकि मैं 302 रीडायरेक्ट प्रतिक्रियाओं को कैप्चर करने में सक्षम नहीं था, इसलिए मैंने LoginPageअपने लॉगिन पेज पर एक हेडर जोड़ा जिसमें लॉगिन पेज का यूआरएल ही था। मॉड्यूल में अब मैं हेडर के लिए सुनता हूं और रीडायरेक्ट करता हूं:

if(xhr.status === 200){
    var loginPageRedirectHeader = xhr.getResponseHeader("LoginPage");
    if(loginPageRedirectHeader && loginPageRedirectHeader !== ""){
        window.location.replace(loginPageRedirectHeader);
    }
}

... और वह आकर्षण की तरह काम करता है :)। आप आश्चर्यचकित हो सकते हैं कि मैंने LoginPageहेडर में यूआरएल क्यों शामिल किया है ... अच्छी तरह से मूल रूप से क्योंकि मुझे ऑब्जेक्ट GETसे स्वचालित रीडायरेक्ट से उत्पन्न यूआरएल के निर्धारण का कोई तरीका नहीं मिला xhr...


+1 - लेकिन कस्टम हेडर शुरू करने वाले हैं X-, इसलिए उपयोग करने के लिए बेहतर हेडर होगा X-LoginPage: http://example.com/login
अपराह्न ४:१२ बजे १२:१२

6
@ShaquinTrifonoff कोई और नहीं। मैंने X- उपसर्ग का उपयोग नहीं किया क्योंकि जून 2011 में एक ITEF दस्तावेज़ ने उनके पदावनति का प्रस्ताव दिया था और वास्तव में, जून 2012 के साथ यह कोई आधिकारिक नहीं है कि कस्टम हेडर के साथ कोई और उपसर्ग नहीं होना चाहिए X-
जूरी

हमारे पास ISA सर्वर भी है और मैं बस उसी मुद्दे में भाग गया। कोड में इसके चारों ओर काम करने के बजाय, हमने पुनर्निर्देशन को रोकने के लिए ISA को कॉन्फ़िगर करने के लिए kb2596444 में निर्देशों का उपयोग किया ।
स्कॉट स्टोन

29

मुझे पता है कि यह विषय पुराना है, लेकिन मैं अभी तक एक और दृष्टिकोण प्रदान करूंगा और यहां पहले वर्णित किया गया था । मूल रूप से मैं WIF के साथ ASP.MVC का उपयोग कर रहा हूं (लेकिन यह इस विषय के संदर्भ के लिए वास्तव में महत्वपूर्ण नहीं है - उत्तर पर्याप्त है कोई फर्क नहीं पड़ता कि कौन से फ्रेमवर्क का उपयोग किया जाता है। सुराग अपरिवर्तित रहता है - अजेय अनुरोध करते समय प्रमाणीकरण विफलताओं से संबंधित मुद्दों से निपटना। ) का है

नीचे दिखाए गए दृष्टिकोण को बॉक्स से बाहर सभी अजाक्स अनुरोधों पर लागू किया जा सकता है (यदि वे घटना को स्पष्ट रूप से पहले से फिर से परिभाषित नहीं करते हैं)।

$.ajaxSetup({
    beforeSend: checkPulse,
    error: function (XMLHttpRequest, textStatus, errorThrown) {
        document.open();
        document.write(XMLHttpRequest.responseText);
        document.close();
    }
});

इससे पहले कि कोई भी अजाक्स अनुरोध किया जाता है CheckPulseविधि लागू की जाती है (नियंत्रक विधि जो सबसे सरल हो सकती है):

[Authorize]
public virtual void CheckPulse() {}

यदि उपयोगकर्ता प्रमाणित नहीं है (टोकन समाप्त हो गया है) तो ऐसी विधि तक पहुँचा नहीं जा सकता ( Authorizeविशेषता द्वारा संरक्षित )। क्योंकि फ्रेमवर्क प्रमाणीकरण संभालता है, जबकि टोकन समाप्त हो जाता है, यह प्रतिक्रिया के लिए http स्थिति 302 डालता है। यदि आप अपने ब्राउज़र को पारदर्शी रूप से 302 प्रतिसाद को संभालना नहीं चाहते हैं, तो उसे Global.asax में बदलें और प्रतिक्रिया की स्थिति बदलें - उदाहरण के लिए 200 OK। इसके अतिरिक्त, हेडर जोड़ें, जो आपको इस तरह की प्रतिक्रिया को विशेष तरीके से संसाधित करने का निर्देश देता है (बाद में ग्राहक पक्ष में):

protected void Application_EndRequest()
{
    if (Context.Response.StatusCode == 302
        && (new HttpContextWrapper(Context)).Request.IsAjaxRequest())
    {                
        Context.Response.StatusCode = 200;
        Context.Response.AddHeader("REQUIRES_AUTH", "1");
    }
}

अंत में ग्राहक की ओर से ऐसे कस्टम हेडर के लिए जाँच करें। यदि मौजूद है - लॉगऑन पेज पर पूर्ण पुनर्निर्देशन किया जाना चाहिए (मेरे मामले window.locationमें अनुरोध से यूआरएल द्वारा प्रतिस्थापित किया जाता है जिसे मेरे ढांचे द्वारा स्वचालित रूप से नियंत्रित किया जाता है)।

function checkPulse(XMLHttpRequest) {
    var location = window.location.href;
    $.ajax({
        url: "/Controller/CheckPulse",
        type: 'GET',
        async: false,
        beforeSend: null,
        success:
            function (result, textStatus, xhr) {
                if (xhr.getResponseHeader('REQUIRES_AUTH') === '1') {
                    XMLHttpRequest.abort(); // terminate further ajax execution
                    window.location = location;
                }
            }
    });
}

मैंने EndRequest इवेंट के बजाय PostAuthenticateRequest इवेंट का उपयोग करके समस्या को ठीक किया।
फ्रिनावले

@JaroslawWaliszko मैंने अपने अंतिम उत्तर में गलत घटना को चिपकाया है! मेरा मतलब PreSendRequestHeaders घटना ..... नहीं PostAuthenticateRequest! >> ब्लश << मेरी गलती को इंगित करने के लिए धन्यवाद।
फ्रिनवैल

WJ का उपयोग करते समय @JaroslawWaliszko आप AJAX अनुरोधों के लिए 401 प्रतिक्रियाएं भी वापस कर सकते हैं और अपने जावास्क्रिप्ट को इनका संचालन करने दें। आप यह भी मान रहे हैं कि सभी 302 को प्रमाणीकरण की आवश्यकता है जो सभी मामलों में सही नहीं हो सकता है। अगर किसी को दिलचस्पी है तो मैंने एक जवाब जोड़ा है।
रोब

26

मुझे लगता है कि इसे संभालने का एक बेहतर तरीका मौजूदा HTTP प्रोटोकॉल प्रतिक्रिया कोड का लाभ उठाना है, विशेष रूप से 401 Unauthorized

यहाँ है कि मैंने इसे कैसे हल किया:

  1. सर्वर साइड: यदि सत्र समाप्त हो जाता है, और अनुरोध ajax है। 401 प्रतिक्रिया कोड हेडर भेजें
  2. ग्राहक पक्ष: अजाक्स घटनाओं के लिए बाध्य करें

    $('body').bind('ajaxSuccess',function(event,request,settings){
    if (401 == request.status){
        window.location = '/users/login';
    }
    }).bind('ajaxError',function(event,request,settings){
    if (401 == request.status){
        window.location = '/users/login';
    }
    });

IMO यह अधिक सामान्य है और आप कुछ नए कस्टम युक्ति / शीर्षक नहीं लिख रहे हैं। आपको अपने किसी भी मौजूदा अजाक्स कॉल को संशोधित नहीं करना चाहिए।

संपादित करें: प्रति @ रोब नीचे टिप्पणी, 401 (प्रमाणीकरण त्रुटियों के लिए HTTP स्थिति कोड) संकेतक होना चाहिए। अधिक विवरण के लिए 403 निषिद्ध बनाम 401 अनधिकृत HTTP प्रतिक्रियाओं को देखें । कहा जा रहा है कि कुछ वेब फ्रेमवर्क प्रमाणीकरण और प्राधिकरण त्रुटियों दोनों के लिए 403 का उपयोग करते हैं - इसलिए तदनुसार अनुकूलित करें। धन्यवाद रॉब।


मैं उसी दृष्टिकोण का उपयोग करता हूं। क्या jQuery वास्तव में ajaxSuccess को 403 त्रुटि कोड पर कॉल करता है? मुझे लगता है कि केवल ajaxError भाग की वास्तव में आवश्यकता है
Marius Balčytis

24

मैंने इस मुद्दे को इस तरह हल किया:

प्रतिक्रिया को संसाधित करने के लिए एक मिडलवेयर जोड़ें, अगर यह एक अजाक्स अनुरोध के लिए रीडायरेक्ट है, तो प्रतिक्रिया को रीडायरेक्ट यूआरएल के साथ एक सामान्य प्रतिक्रिया में बदल दें।

class AjaxRedirect(object):
  def process_response(self, request, response):
    if request.is_ajax():
      if type(response) == HttpResponseRedirect:
        r = HttpResponse(json.dumps({'redirect': response['Location']}))
        return r
    return response

फिर ajaxComplete में, यदि प्रतिक्रिया में पुनर्निर्देशित होता है, तो यह पुनर्निर्देशित होना चाहिए, इसलिए ब्राउज़र का स्थान बदलें।

$('body').ajaxComplete(function (e, xhr, settings) {
   if (xhr.status == 200) {
       var redirect = null;
       try {
           redirect = $.parseJSON(xhr.responseText).redirect;
           if (redirect) {
               window.location.href = redirect.replace(/\?.*$/, "?next=" + window.location.pathname);
           }
       } catch (e) {
           return;
       }
   }
}

20

मेरे पास एक सरल समाधान है जो मेरे लिए काम करता है, कोई सर्वर कोड परिवर्तन की आवश्यकता नहीं है ... बस जायफल का एक चम्मच जोड़ें ...

$(document).ready(function ()
{
    $(document).ajaxSend(
    function(event,request,settings)
    {
        var intercepted_success = settings.success;
        settings.success = function( a, b, c ) 
        {  
            if( request.responseText.indexOf( "<html>" ) > -1 )
                window.location = window.location;
            else
                intercepted_success( a, b, c );
        };
    });
});

मैं html टैग की उपस्थिति की जांच करता हूं, लेकिन आप अपने लॉगिन पृष्ठ में जो भी अद्वितीय स्ट्रिंग मौजूद है, उसे खोजने के लिए indexOf को बदल सकते हैं ...


यह मेरे लिए काम नहीं करता है, यह अजाक्स कॉल के साथ परिभाषित फ़ंक्शन को कॉल करता रहता है, यह ऐसा है जैसे यह सफलता की विधि को ओवरराइड नहीं कर रहा है।
adriaanp

मेरे लिए काम नहीं कर रहा है, कम से कम अब और नहीं। यहाँ संभावित व्याख्या: stackoverflow.com/a/12010724/260665
राज पवन गुमडाल

20

एक अन्य समाधान मुझे मिला (विशेष रूप से उपयोगी यदि आप एक वैश्विक व्यवहार सेट करना चाहते हैं) संपत्ति के साथ मिलकर $.ajaxsetup()विधि का उपयोग करना statusCodeहै । अन्य लोगों की तरह, एक रीडायरेक्ट स्थिति कोड ( 3xx) का उपयोग न करें , इसके बजाय एक स्थिति कोड का उपयोग करें 4xxऔर पुनर्निर्देशित क्लाइंट-साइड को हैंडल करें।

$.ajaxSetup({ 
  statusCode : {
    400 : function () {
      window.location = "/";
    }
  }
});

उस स्थिति-स्थिति से बदलें 400जिसे आप संभालना चाहते हैं। जैसा कि पहले ही उल्लेख 401 Unauthorizedकिया गया है एक अच्छा विचार हो सकता है। मैं उपयोग करता हूं 400क्योंकि यह बहुत अनिर्दिष्ट है और मैं 401अधिक विशिष्ट मामलों (जैसे गलत लॉगिन क्रेडेंशियल्स) के लिए उपयोग कर सकता हूं । इसलिए 4xxसत्र को समय समाप्त होने पर सीधे आपके बैकएंड को पुनर्निर्देशित करने के बजाय आपको एक त्रुटि-कोड वापस करना चाहिए और आप रीडायरेक्ट क्लाइंट-साइड को हैंडल करते हैं। रीढ़ की हड्डी जैसे फ्रेम के साथ भी मेरे लिए एकदम सही है


पृष्ठ पर फ़ंक्शन का उल्लेख कहां करें?
विक्रांत

@ विक्रांत यदि मैं आपके प्रश्न को सही ढंग से समझता हूं, तो आप jQuery लोड होने के बाद और अपने वास्तविक अनुरोधों को करने से पहले फ़ंक्शन को सही तरीके से कॉल कर सकते हैं।
मोर्टन.सी।

19

दिए गए समाधानों में से अधिकांश एक अतिरिक्त हेडर या एक अनुचित HTTP कोड का उपयोग करते हुए, वर्कअराउंड का उपयोग करते हैं। वे समाधान शायद सबसे ज्यादा काम आएंगे लेकिन थोड़ा सा 'हैकी' महसूस करेंगे। मैं एक और समाधान के साथ आया हूं।

हम WIF का उपयोग कर रहे हैं जो 401 की प्रतिक्रिया पर पुनर्निर्देशित किया गया है (passiveRedirectEnabled = "true")। रीडायरेक्ट सामान्य अनुरोधों को संभालने के दौरान उपयोगी होता है, लेकिन AJAX अनुरोधों के लिए काम नहीं करेगा (क्योंकि ब्राउज़र 302 / रीडायरेक्ट निष्पादित नहीं करेंगे)।

अपने Global.asax में निम्नलिखित कोड का उपयोग करके आप AJAX अनुरोधों के लिए रीडायरेक्ट को अक्षम कर सकते हैं:

    void WSFederationAuthenticationModule_AuthorizationFailed(object sender, AuthorizationFailedEventArgs e)
    {
        string requestedWithHeader = HttpContext.Current.Request.Headers["X-Requested-With"];

        if (!string.IsNullOrEmpty(requestedWithHeader) && requestedWithHeader.Equals("XMLHttpRequest", StringComparison.OrdinalIgnoreCase))
        {
            e.RedirectToIdentityProvider = false;
        }
    }

यह आपको AJAX अनुरोधों के लिए 401 प्रतिक्रियाओं को वापस करने की अनुमति देता है, जिसे आपकी जावास्क्रिप्ट तब पृष्ठ को पुनः लोड करके संभाल सकती है। पृष्ठ को फिर से लोड करने पर एक 401 फेंक देगा जिसे WIF द्वारा नियंत्रित किया जाएगा (और WIF उपयोगकर्ता को लॉगिन पृष्ठ पर पुनर्निर्देशित करेगा)।

401 त्रुटियों को संभालने के लिए एक उदाहरण जावास्क्रिप्ट:

$(document).ajaxError(function (event, jqxhr, settings, exception) {

    if (jqxhr.status == 401) { //Forbidden, go to login
        //Use a reload, WIF will redirect to Login
        location.reload(true);
    }
});

अच्छा समाधान। धन्यवाद।
14

19

ASP.NET MVC RedirectToAction पद्धति का उपयोग करके यह समस्या तब दिखाई दे सकती है। डिव में प्रतिक्रिया को प्रदर्शित करने वाले फ़ॉर्म को रोकने के लिए आप बस $ .ajaxSetup के साथ इनकमिंग प्रतिक्रियाओं के लिए किसी प्रकार का एज़ैक्स प्रतिक्रिया फ़िल्टर कर सकते हैं । यदि प्रतिक्रिया में MVC पुनर्निर्देशन शामिल है तो आप JS की ओर इस अभिव्यक्ति का मूल्यांकन कर सकते हैं। नीचे जेएस के लिए उदाहरण कोड:

$.ajaxSetup({
    dataFilter: function (data, type) {
        if (data && typeof data == "string") {
            if (data.indexOf('window.location') > -1) {
                eval(data);
            }
        }
        return data;
    }
});

यदि डेटा है: "window.location = '/ Acount / Login'" उपरोक्त फ़िल्टर को पकड़ा जाएगा और डेटा को प्रदर्शित होने देने के बजाय पुनर्निर्देशन करने के लिए मूल्यांकन करेगा।


dataप्रतिक्रिया बॉडी या हेडर में है?
GMsoF

16

व्लादिमीर प्रुडनिकोव और थॉमस हेन्सन ने एक साथ कहा:

  • यह पता लगाने के लिए कि क्या यह XHR है, अपना सर्वर-साइड कोड बदलें। यदि ऐसा है, तो अनुप्रेषण की प्रतिक्रिया कोड को 278 पर सेट करें। django में:
   if request.is_ajax():
      response.status_code = 278

यह ब्राउज़र की प्रतिक्रिया को एक सफलता के रूप में मानता है, और इसे आपकी जावास्क्रिप्ट को सौंप देता है।

  • अपने जेएस में, सुनिश्चित करें कि फॉर्म जमा अजाक्स के माध्यम से है, प्रतिक्रिया कोड की जांच करें और यदि आवश्यक हो तो पुनर्निर्देशित करें:
$('#my-form').submit(function(event){ 

  event.preventDefault();   
  var options = {
    url: $(this).attr('action'),
    type: 'POST',
    complete: function(response, textStatus) {    
      if (response.status == 278) { 
        window.location = response.getResponseHeader('Location')
      }
      else { ... your code here ... } 
    },
    data: $(this).serialize(),   
  };   
  $.ajax(options); 
});

13
    <script>
    function showValues() {
        var str = $("form").serialize();
        $.post('loginUser.html', 
        str,
        function(responseText, responseStatus, responseXML){
            if(responseStatus=="success"){
                window.location= "adminIndex.html";
            }
        });     
    }
</script>

12

प्रयत्न

    $(document).ready(function () {
        if ($("#site").length > 0) {
            window.location = "<%= Url.Content("~") %>" + "Login/LogOn";
        }
    });

इसे लॉगिन पेज पर डालें। यदि यह मुख्य पृष्ठ पर एक div में लोड किया गया था, तो यह लॉगिन पेज को रीडायरेक्ट करेगा। "#site" एक div की एक आईडी है जो लॉगिन पेज को छोड़कर सभी पृष्ठों पर स्थित है।


12

यदि आप स्प्रिंग सिक्योरिटी का उपयोग कर रहे हैं तो मुझे लगता है कि लोगों के लिए उत्तर काम कर रहे हैं। अधिकांश उदाहरण सभी को रोकते हैं पुनर्निर्देशों को केवल प्रमाणीकरण विफलताओं को । मैं जिस परियोजना पर काम करता हूं, उसके लिए यह अवांछनीय था। यदि आप असफल AJAX अनुरोध को कैश नहीं करना चाहते हैं तो आप कैशिंग स्टेप को निकालने के लिए ExceptionTranslationFilter का विस्तार करने और "SendStartAuthentication" विधि को ओवरराइड करने की आवश्यकता भी पा सकते हैं।

उदाहरण AjaxAwareAuthenticationEntryPoint:

public class AjaxAwareAuthenticationEntryPoint extends
    LoginUrlAuthenticationEntryPoint {

    public AjaxAwareAuthenticationEntryPoint(String loginUrl) {
        super(loginUrl);
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        if (isAjax(request)) {
            response.sendError(HttpStatus.UNAUTHORIZED.value(), "Please re-authenticate yourself");
        } else {
        super.commence(request, response, authException);
        }
    }

    public static boolean isAjax(HttpServletRequest request) {
        return request != null && "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
    }
}

स्रोत: 1 , 2


3
यह मददगार होगा (मेरे लिए) अगर मतदाता समझाते कि वे मतदान क्यों कर रहे हैं। अगर इस समाधान के साथ कुछ बुरा है, तो मैं अपनी गलतियों से सीखना चाहूंगा। धन्यवाद।
जॉन

यदि स्प्रिंग का उपयोग करना और JSF का उपयोग करना भी है, तो इसके लिए भी जांच करें: ("आंशिक / ajax")। equalsIgnoreCase (request.getHeader ("चेहरे-अनुरोध"));
जे स्लिक

उपयोगकर्ताओं ने वोट दिया हो सकता है क्योंकि आपने उल्लेख नहीं किया है: (1) आपकी त्रुटि प्रतिक्रिया का पता लगाने के लिए अपेक्षित क्लाइंट-साइड मॉड; (2) फ़िल्टर मोड में अपने पसंदीदा LoginUrlAuthenticationEntryPoint को जोड़ने के लिए स्प्रिंग कॉन्फ़िगरेशन के लिए अपेक्षित मॉड।
जे स्लिक

आपका उत्तर @Arpad के समान है। इसने मेरे लिए काम किया; वसंत सुरक्षा का उपयोग 3.2.9। stackoverflow.com/a/8426947/4505142
डैरेन पार्कर

11

मैंने इसे अपने login.php पृष्ठ में निम्नलिखित डालकर हल किया।

<script type="text/javascript">
    if (top.location.href.indexOf('login.php') == -1) {
        top.location.href = '/login.php';
    }
</script>

10

मुझे @Steg द्वारा बताई गई समस्या के बारे में बताएं

मुझे भी आपकी ऐसी ही समस्या थी। मैं एक अजाक्स अनुरोध करता हूं जिसमें 2 संभावित प्रतिक्रियाएं हैं: एक जो ब्राउज़र को एक नए पृष्ठ पर पुनर्निर्देशित करता है और एक जो वर्तमान पृष्ठ पर मौजूदा HTML फॉर्म को नए के साथ बदलता है।

IMHO यह एक वास्तविक चुनौती है और इसे आधिकारिक तौर पर वर्तमान HTTP मानकों के लिए विस्तारित करना होगा।

मेरा मानना ​​है कि नया Http Standard एक नया स्टेटस-कोड इस्तेमाल करेगा। अर्थ: वर्तमान 301/302में ब्राउज़र को इस अनुरोध की सामग्री को एक नए पर जाने और लाने के लिए कहता है location

विस्तारित मानक में, यह कहेगा कि यदि प्रतिक्रिया status: 308(केवल एक उदाहरण) है, तो ब्राउज़र को locationप्रदान किए गए मुख्य पृष्ठ को पुनर्निर्देशित करना चाहिए ।

ऐसा कहे जाने के बाद; मैं पहले से ही इस भविष्य के व्यवहार की नकल करने के लिए इच्छुक हूं , और इसलिए जब एक document.redirect की आवश्यकता होती है, तो मेरे पास सर्वर प्रतिक्रिया है:

status: 204 No Content
x-status: 308 Document Redirect
x-location: /login.html

जब JS " status: 204" हो जाता है , तो यह x-status: 308हेडर के अस्तित्व की जाँच करता है , और locationहेडर में दिए गए पृष्ठ पर एक दस्तावेज़ ।

क्या आपको यह बात ठीक लगती है?


7

कुछ नीचे उपयोगी मिल सकता है:

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

यही मैंने किया है:

किसी भी अजाक्स अनुरोध पर मेरा सर्वर एक JSON 200 प्रतिक्रिया "NEED TO AUTHENTICATE" (यदि क्लाइंट को प्रमाणित करने की आवश्यकता है) वापस कर देगा।

जावा (सर्वर साइड) में सरल उदाहरण:

@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {

    private final Logger m_logger = LoggerFactory.getLogger(AuthenticationFilter.class);

    public static final String COOKIE_NAME = "token_cookie"; 

    @Override
    public void filter(ContainerRequestContext context) throws IOException {        
        // Check if it has a cookie.
        try {
            Map<String, Cookie> cookies = context.getCookies();

            if (!cookies.containsKey(COOKIE_NAME)) {
                m_logger.debug("No cookie set - redirect to login page");
                throw new AuthenticationException();
            }
        }
        catch (AuthenticationException e) {
            context.abortWith(Response.ok("\"NEED TO AUTHENTICATE\"").type("json/application").build());
        }
    }
}

मेरे जावास्क्रिप्ट में मैंने निम्नलिखित कोड जोड़ा है:

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    var originalSuccess = options.success;

    options.success = function(data) {
        if (data == "NEED TO AUTHENTICATE") {
            window.location.replace("/login.html");
        }
        else {
            originalSuccess(data);
        }
    };      
});

और इसके बारे में है।


5

सर्वलेट में आपको रखना चाहिए response.setStatus(response.SC_MOVED_PERMANENTLY); '301' xmlHttp स्थिति भेजने के लिए जिसे आपको पुनर्निर्देशन की आवश्यकता है ...

और $ .ajax फ़ंक्शन में आपको फ़ंक्शन का उपयोग नहीं करना चाहिए .toString()..., बस

if (xmlHttp.status == 301) { top.location.href = 'xxxx.jsp'; }

समस्या यह है कि यह बहुत लचीला नहीं है, आप यह तय नहीं कर सकते कि आप कहाँ पुनर्निर्देशित करना चाहते हैं ..

सर्वलेट्स के माध्यम से पुनर्निर्देशन सबसे अच्छा तरीका होना चाहिए। लेकिन मुझे अभी भी इसे करने का सही तरीका नहीं मिल रहा है।


5

मैं सिर्फ पूरे पृष्ठ के लिए किसी भी ajax अनुरोधों को लागू करना चाहता था। @SuperG मुझे शुरू कर दिया। यहाँ मैं के साथ समाप्त हो गया है:

// redirect ajax requests that are redirected, not found (404), or forbidden (403.)
$('body').bind('ajaxComplete', function(event,request,settings){
        switch(request.status) {
            case 301: case 404: case 403:                    
                window.location.replace("http://mysite.tld/login");
                break;
        }
});

मैं अपने निर्णय को आधार बनाने के लिए विशेष रूप से कुछ http स्थिति कोड की जांच करना चाहता था। हालाँकि, आप सिर्फ सफलता के अलावा और कुछ पाने के लिए ajaxError से बंध सकते हैं (200 केवल शायद?) मैं सिर्फ इतना कर सकता था:

$('body').bind('ajaxError', function(event,request,settings){
    window.location.replace("http://mysite.tld/login");
}

1
उत्तरार्द्ध समस्या निवारण समस्या निवारण करने वाली अन्य त्रुटियों को छिपाएगा
टिम एबेल

1
403 का मतलब यह नहीं है कि उपयोगकर्ता प्रमाणित नहीं है, इसका मतलब है कि (शायद प्रमाणित) उपयोगकर्ता के पास अनुरोधित संसाधन को देखने की अनुमति नहीं है। तो यह लॉगिन पृष्ठ पर पुनः निर्देशित नहीं करना चाहिए
रोब

5

यदि आप भी मानों को पास करना चाहते हैं तो आप सत्र चर भी सेट कर सकते हैं और एग का उपयोग कर सकते हैं: अपने जेएसपी में आप लिख सकते हैं

<% HttpSession ses = request.getSession(true);
   String temp=request.getAttribute("what_you_defined"); %>

और फिर आप अपने जावास्क्रिप्ट चर में इस अस्थायी मूल्य को स्टोर कर सकते हैं और चारों ओर खेल सकते हैं


5

हेडर समाधान के साथ मुझे कोई सफलता नहीं मिली - वे मेरे ajaxSuccess / ajaxComplete विधि में कभी नहीं उठाए गए थे। मैंने कस्टम प्रतिक्रिया के साथ स्टेग के उत्तर का उपयोग किया, लेकिन मैंने जेएस पक्ष को संशोधित किया। मैं एक विधि सेट करता हूं जिसे मैं प्रत्येक फ़ंक्शन में कॉल करता हूं ताकि मैं मानक $.getऔर $.postविधियों का उपयोग कर सकूं।

function handleAjaxResponse(data, callback) {
    //Try to convert and parse object
    try {
        if (jQuery.type(data) === "string") {
            data = jQuery.parseJSON(data);
        }
        if (data.error) {
            if (data.error == 'login') {
                window.location.reload();
                return;
            }
            else if (data.error.length > 0) {
                alert(data.error);
                return;
            }
        }
    }
    catch(ex) { }

    if (callback) {
        callback(data);
    }
}

उपयोग में इसका उदाहरण ...

function submitAjaxForm(form, url, action) {
    //Lock form
    form.find('.ajax-submit').hide();
    form.find('.loader').show();

    $.post(url, form.serialize(), function (d) {
        //Unlock form
        form.find('.ajax-submit').show();
        form.find('.loader').hide();

        handleAjaxResponse(d, function (data) {
            // ... more code for if auth passes ...
        });
    });
    return false;
}

5

अंत में, मैं एक कस्टम जोड़कर समस्या को हल करता हूं HTTP Header। सर्वर साइड में प्रत्येक अनुरोध के लिए प्रतिक्रिया से पहले, मैं प्रतिक्रिया के हेडर के लिए वर्तमान अनुरोधित यूआरएल को जोड़ता हूं।

सर्वर पर मेरा एप्लिकेशन प्रकार है Asp.Net MVC, और इसे करने के लिए एक अच्छी जगह है। में Global.asaxमैंने इस Application_EndRequestकार्यक्रम को लागू किया :

    public class MvcApplication : System.Web.HttpApplication
    {

    //  ...
    //  ...

        protected void Application_EndRequest(object sender, EventArgs e)
        {
            var app = (HttpApplication)sender;
            app.Context.Response.Headers.Add("CurrentUrl",app.Context. Request.CurrentExecutionFilePath);
        }

    }

यह मेरे लिए एकदम सही काम करता है! अब आई की हर प्रतिक्रिया में JQuery $.postअनुरोध urlऔर अन्य प्रतिक्रिया हेडर हैं, जो POSTस्थिति के अनुसार विधि के परिणाम के रूप में आते हैं 302,303 ...।

और अन्य महत्वपूर्ण बात यह है कि सर्वर साइड पर न तो कोड को संशोधित करने की आवश्यकता है और न ही क्लाइंट साइड की।

और अगली पोस्ट एक्शन की अन्य जानकारी तक पहुँचने की क्षमता है, इस तरह की त्रुटियाँ, संदेश, और ..., इस तरह से।

मैंने इसे पोस्ट किया है, शायद किसी की मदद करें :)


4

मुझे यह समस्या एक django ऐप पर हो रही है, जिसके साथ मैं छेड़छाड़ कर रहा हूं (अस्वीकरण: मैं सीखने के लिए टिंकर कर रहा हूं, और किसी भी तरह से विशेषज्ञ नहीं हूं)। जो मैं करना चाहता था वह एक संसाधन के लिए DELETE अनुरोध भेजने के लिए jQuery के ajax का उपयोग करना था, इसे सर्वर की तरफ हटाना, फिर होमपेज पर (मूल रूप से) रीडायरेक्ट वापस भेजना। जब मैंने HttpResponseRedirect('/the-redirect/')अजगर स्क्रिप्ट से भेजा , jQuery की अजाक्स विधि 302 के बजाय 200 प्राप्त कर रही थी। इसलिए, मैंने जो किया वह 300 की प्रतिक्रिया भेजना था:

response = HttpResponse(status='300')
response['Location'] = '/the-redirect/' 
return  response

फिर मैंने jQuery.ajax के साथ क्लाइंट पर अनुरोध भेजा / भेजा जैसे:

<button onclick="*the-jquery*">Delete</button>

where *the-jquery* =
$.ajax({ 
  type: 'DELETE', 
  url: '/resource-url/', 
  complete: function(jqxhr){ 
    window.location = jqxhr.getResponseHeader('Location'); 
  } 
});

शायद 300 का उपयोग करना "सही" नहीं है, लेकिन कम से कम यह ठीक वैसे ही काम करता है जैसे मैं चाहता था।

पुनश्च: यह एसओ के मोबाइल संस्करण पर संपादित करने के लिए एक बड़ा दर्द था। मूर्ख आईएसपी ने मेरे जवाब के साथ मेरे सेवा रद्द करने के अनुरोध को सही तरीके से रखा!


4

आप XMLHttpRequest send प्रोटोटाइप को हुक भी कर सकते हैं। यह एक हैंडलर के साथ सभी भेजने (jQuery / dojo / etc) के लिए काम करेगा।

मैंने 500 कोड की समय सीमा समाप्त त्रुटि को संभालने के लिए यह कोड लिखा था, लेकिन यह 200 पुनर्निर्देशित करने के लिए बस काम करना चाहिए। तैयार के अर्थ के बारे में XMLHttpRequest onreadystatechange पर विकिपीडिया प्रविष्टि तैयार करें ।

// Hook XMLHttpRequest
var oldXMLHttpRequestSend = XMLHttpRequest.prototype.send;

XMLHttpRequest.prototype.send = function() {
  //console.dir( this );

  this.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 500 && this.responseText.indexOf("Expired") != -1) {
      try {
        document.documentElement.innerHTML = this.responseText;
      } catch(error) {
        // IE makes document.documentElement read only
        document.body.innerHTML = this.responseText;
      }
    }
  };

  oldXMLHttpRequestSend.apply(this, arguments);
}

2

इसके अतिरिक्त आप शायद हेडर URL में दिए गए उपयोगकर्ता को पुनर्निर्देशित करना चाहेंगे। तो अंत में यह इस तरह दिखेगा:

$.ajax({
    //.... other definition
    complete:function(xmlHttp){
        if(xmlHttp.status.toString()[0]=='3'){
        top.location.href = xmlHttp.getResponseHeader('Location');
    }
});

UPD: विरोध करता है। एक ही कार्य है, लेकिन यह काम नहीं करता है। यह सामान करना। जब मैं खोज लूंगा तब आपको समाधान दिखाऊंगा


4
इस उत्तर को लेखक द्वारा हटा दिया जाना चाहिए क्योंकि वह स्वयं कहता है कि यह काम नहीं करता है। वह बाद में एक कार्य समाधान पोस्ट कर सकता है। -1
TheCrazyProgrammer

विचार अच्छा है, लेकिन समस्या यह है कि "स्थान" शीर्षक कभी भी पारित नहीं होता है।
मार्टिन Zvarík

मेरा संपादन अस्वीकार कर दिया गया था, इसलिए ... आपको "var xmlHttp = $ .ajax ({...." का उपयोग करना होगा जो चर अंदर नहीं हो सकता ... फिर उपयोग करें: कंसोल .log (xmlHttp.getAllResponseHeaders ()) ;
मार्टिन ज़वारिक

2

मुझे @John और @Arpad लिंक और @RobWinch लिंक के उत्तरों का उपयोग करके एक कार्यशील सॉल्यूशन मिला

मैं स्प्रिंग सुरक्षा 3.2.9 और jQuery 1.10.2 का उपयोग करता हूं।

AJAX अनुरोधों से केवल 4XX प्रतिक्रिया देने के लिए स्प्रिंग की कक्षा बढ़ाएँ:

public class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {

    public CustomLoginUrlAuthenticationEntryPoint(final String loginFormUrl) {
        super(loginFormUrl);
    }

    // For AJAX requests for user that isn't logged in, need to return 403 status.
    // For normal requests, Spring does a (302) redirect to login.jsp which the browser handles normally.
    @Override
    public void commence(final HttpServletRequest request,
                         final HttpServletResponse response,
                         final AuthenticationException authException)
            throws IOException, ServletException {
        if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
        } else {
            super.commence(request, response, authException);
        }
    }
}

applicationContext-security.xml

  <security:http auto-config="false" use-expressions="true" entry-point-ref="customAuthEntryPoint" >
    <security:form-login login-page='/login.jsp' default-target-url='/index.jsp'                             
                         authentication-failure-url="/login.jsp?error=true"
                         />    
    <security:access-denied-handler error-page="/errorPage.jsp"/> 
    <security:logout logout-success-url="/login.jsp?logout" />
...
    <bean id="customAuthEntryPoint" class="com.myapp.utils.CustomLoginUrlAuthenticationEntryPoint" scope="singleton">
        <constructor-arg value="/login.jsp" />
    </bean>
...
<bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache">
    <property name="requestMatcher">
      <bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
        <constructor-arg>
          <bean class="org.springframework.security.web.util.matcher.MediaTypeRequestMatcher">
            <constructor-arg>
              <bean class="org.springframework.web.accept.HeaderContentNegotiationStrategy"/>
            </constructor-arg>
            <constructor-arg value="#{T(org.springframework.http.MediaType).APPLICATION_JSON}"/>
            <property name="useEquals" value="true"/>
          </bean>
        </constructor-arg>
      </bean>
    </property>
</bean>

मेरे जेएसपी में, एक वैश्विक AJAX त्रुटि हैंडलर जोड़ें जैसा कि यहां दिखाया गया है

  $( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
      if ( jqxhr.status === 403 ) {
          window.location = "login.jsp";
      } else {
          if(thrownError != null) {
              alert(thrownError);
          } else {
              alert("error");
          }
      }
  });

इसके अलावा, JSP पृष्ठों में AJAX कॉल से मौजूदा त्रुटि संचालकों को हटा दें:

        var str = $("#viewForm").serialize();
        $.ajax({
            url: "get_mongoDB_doc_versions.do",
            type: "post",
            data: str,
            cache: false,
            async: false,
            dataType: "json",
            success: function(data) { ... },
//            error: function (jqXHR, textStatus, errorStr) {
//                 if(textStatus != null)
//                     alert(textStatus);
//                 else if(errorStr != null)
//                     alert(errorStr);
//                 else
//                     alert("error");
//            }
        });

मुझे उम्मीद है कि यह दूसरों की मदद करता है।

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

Update2 उपयोग करने के बजाय always-use-default-target="true", अपेक्षित पोस्ट से AJAX अनुरोधों को अवरुद्ध करने के @RobWinch उदाहरण का उपयोग करें। यह सामान्य लिंक को लॉगिन के बाद अपने मूल लक्ष्य पर पुनर्निर्देशित करने की अनुमति देता है, लेकिन AJAX लॉगिन के बाद होम पेज पर जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.