วิธีป้องกันการร้องขอ ajax เพื่อติดตามการเปลี่ยนเส้นทางโดยใช้ jQuery


103

ฉันใช้ฟังก์ชัน jQuery ajax เพื่อเข้าถึงบริการเว็บ แต่เซิร์ฟเวอร์แทนที่จะส่งคืนการตอบกลับด้วยรหัสสถานะที่อธิบายปัญหาคำขอจะถูกเปลี่ยนเส้นทางไปยังหน้าที่มีส่วนหัว 200 ซึ่งอธิบายปัญหา ฉันไม่สามารถทำการเปลี่ยนแปลงใด ๆ กับสิ่งนี้ได้ดังนั้นฉันจึงต้องแก้ปัญหาบนไคลเอนต์อย่างใด

ตัวอย่าง: คำขอไปยัง URL บางรายการซึ่งไม่พบดังนั้นฉันจึงได้รับ 302 Redirect ไปยังตำแหน่งอื่น มีการส่งคำขอใหม่และฉันได้รับ 200 OK ดังนั้นจึงป้องกันไม่ให้เกิดข้อผิดพลาดในการโทรกลับ

มีวิธีใดบ้างที่ฉันสามารถป้องกันคำขอ ajax เพื่อติดตามการเปลี่ยนเส้นทางและเรียกใช้การโทรกลับแทนโดยควรใช้วิธีการแสดงข้อผิดพลาด อีกวิธีหนึ่งเป็นไปได้หรือไม่ที่จะตรวจพบว่ามีการเปลี่ยนเส้นทางเกิดขึ้นในไคลเอนต์หรือไม่?


สิ่งนี้สามารถช่วยได้: stackoverflow.com/questions/1804928/handle-jquery-ajax-redirect
PiTheNumber

8
เป็นเรื่องแปลกที่แบ็กเอนด์ของคุณรายงาน 302 สำหรับสิ่งที่ไม่พบแทนที่จะเป็น 404
Jake Feasel

คำตอบ:


96

ฉันคิดว่าคำถามของคุณน่าสนใจ แต่ปัญหาโดยรวมดูเหมือนว่าฉันจะเข้าใจผิดมากกว่า อย่างน้อยฉันจะพยายามอธิบายความเข้าใจของฉันเกี่ยวกับปัญหา

การเปลี่ยนเส้นทางแบบเงียบ (โปร่งใส) เป็นส่วนหนึ่งของXMLHttpRequestข้อกำหนด (ดูที่นี่โดยเฉพาะคำว่า "... ทำตามการเปลี่ยนเส้นทางอย่างโปร่งใส ... ") กล่าวถึงมาตรฐานเดียวที่ตัวแทนผู้ใช้ (เว็บเบราว์เซอร์) สามารถป้องกันหรือแจ้งของบางชนิดของการเปลี่ยนเส้นทางโดยอัตโนมัติ XMLHttpRequestแต่มันไม่ได้เป็นส่วนหนึ่งของ เป็นส่วนของการกำหนดค่าไคลเอ็นต์ HTTP (การกำหนดค่าระบบปฏิบัติการ) หรือการกำหนดค่าเว็บเบราว์เซอร์ ดังนั้นจึงjQuery.ajaxไม่มีตัวเลือกใดที่คุณสามารถป้องกันการเปลี่ยนเส้นทางได้

คุณจะเห็นว่าการเปลี่ยนเส้นทาง HTTP เป็นส่วนหนึ่งของโปรโตคอล HTTP XMLHttpRequestและไม่ใช่ส่วนหนึ่งของ ดังนั้นมันจึงอยู่ในอีกระดับของนามธรรมหรือเครือข่ายสแต็ก ตัวอย่างเช่นข้อมูลจากXMLHttpRequestสามารถดึงจากพร็อกซี HTTP หรือจากแคชของเบราว์เซอร์ในเครื่องและเป็นส่วนหนึ่งของโปรโตคอล HTTP ส่วนใหญ่เป็นเซิร์ฟเวอร์ที่ให้ข้อมูลและไม่ใช่ไคลเอนต์ที่มีผลต่อการแคช

คุณสามารถเปรียบเทียบข้อกำหนดจากคำถามของคุณกับข้อกำหนดเพื่อป้องกันการเปลี่ยนที่อยู่ IP ของเว็บเซิร์ฟเวอร์หรือการเปลี่ยนเส้นทาง IP ระหว่างการสื่อสาร ทุกสิ่งที่สามารถที่น่าสนใจในบางสถานการณ์ แต่มีบางส่วนของระดับของสแต็คการสื่อสารอื่นและไม่สามารถจัดการได้โดยหรือjQuery.ajaxXMLHttpRequest

XMLHttpRequestกล่าวว่าการกำหนดค่ามาตรฐานลูกค้าสามารถมีตัวเลือกซึ่งจะช่วยป้องกันการเปลี่ยนเส้นทาง ในกรณีของ "Microsoft world" ซึ่งฉันรู้ดีกว่าคุณสามารถดูที่ฟังก์ชันWinHttpSetOptionซึ่งสามารถใช้เพื่อตั้งค่าWINHTTP_OPTION_DISABLE_FEATUREตัวเลือกด้วยWINHTTP_DISABLE_REDIRECTSค่า อีกวิธีหนึ่งคือการใช้WINHTTP_OPTION_REDIRECT_POLICYตัวเลือกที่มีWINHTTP_OPTION_REDIRECT_POLICY_NEVERค่า หนึ่งคุณลักษณะเพิ่มเติมที่หนึ่งที่สามารถใช้ในการ Windows เป็นWinHttpSetStatusCallbackWINHTTP_CALLBACK_FLAG_REDIRECTฟังก์ชั่นที่สามารถตั้งค่าฟังก์ชั่นการโทรกลับได้รับการแจ้งเตือนบางอย่างเช่น

ดังนั้นจึงเป็นไปได้ที่จะทำใช้ความต้องการของคุณในทั่วไป แต่การแก้ปัญหาจะต้องอาจจะไม่ได้เป็นอิสระจากระบบการดำเนินงานหรือเว็บเบราเซอร์และจะไม่ได้อยู่ในระดับหรือjQuery.ajaxXMLHttpRequest


2
คำตอบที่ยอดเยี่ยมพร้อมข้อมูลเชิงลึก! ฉันมีประสบการณ์เกี่ยวกับ curl ซึ่งคุณสามารถตั้งค่าสถานะที่คล้ายกันได้ตามที่คุณพูดถึง ฉันหวังว่าจะสามารถส่งคำแนะนำดังกล่าวไปยังเบราว์เซอร์ได้ แต่จากคำตอบของคุณฉันเข้าใจว่าพฤติกรรมที่คาดไว้จะเป็นไปตามการเปลี่ยนเส้นทางราวกับว่าคำขอเริ่มต้นถูกส่งไปยังตำแหน่งที่กำหนดโดยเซิร์ฟเวอร์
Jørgen

@ Jørgen: ยินดีต้อนรับ! ในสถานการณ์ส่วนใหญ่การเปลี่ยนเส้นทางไม่ใช่ปัญหา แต่อย่างใด คุณไม่ได้อธิบายบริบทที่คุณใช้ jQuery.ajax และคุณสามารถควบคุมเว็บเซิร์ฟเวอร์ที่คุณส่งคำขอได้ทั้งหมดหรือไม่ ดังนั้นจึงเป็นเรื่องยากที่จะให้คำแนะนำอื่น ๆ ที่สามารถแก้ปัญหาของคุณได้
Oleg

ฉันไม่ได้ควบคุมฝั่งเซิร์ฟเวอร์ฉันกลัว ฉันเดาว่าตัวเลือกที่ดีที่สุดของฉันคือวิเคราะห์หรือตรวจสอบเนื้อหาการตอบกลับ
Jørgen

@ Jørgen: เหตุใดการเปลี่ยนเส้นทางจึงเป็นปัญหาในกรณีของคุณ? หากเซิร์ฟเวอร์ย้ายเพจบางเพจไปที่ตำแหน่งอื่นชั่วคราวหรือถาวรก็สามารถเปลี่ยนเส้นทางคำขอเดิมของคุณไปยังตำแหน่งใหม่ได้ มันจะตกลงอย่างแน่นอน ผู้ดูแลระบบสามารถกำหนดค่าเว็บเซิร์ฟเวอร์ให้ทำการเปลี่ยนเส้นทางเช่นในระหว่างการดำเนินการกู้คืนบนเซิร์ฟเวอร์หรืองานสนับสนุนอื่น ๆ หากคุณถามเซิร์ฟเวอร์ตาม URL ที่มี DNS ผู้ดูแลระบบสามารถเปลี่ยนการแมป IP ไปยังเซิร์ฟเวอร์อื่นได้ เขาสามารถทำการเปลี่ยนเส้นทาง HTTP ในลักษณะเดียวกับการกำหนดค่า DNS ใหม่ คุณมีปัญหาอะไร?
Oleg

ปัญหาของฉันคือการเปลี่ยนเส้นทางไปที่หน้าข้อผิดพลาดทั่วไป ฉันรู้ว่าควรตั้งค่าเซิร์ฟเวอร์ให้แตกต่างกันไป แต่ตอนนี้ฉันต้องหาวิธีแก้ไขสำหรับสถานการณ์นี้เหมือนเดิม
Jørgen

23

ฉันไม่เชื่อว่ามันจะเป็นไปได้ ไลบรารีต้นแบบ (XHR) ทำให้คำขอใหม่โปร่งใส ดังที่กล่าวไว้สิ่งที่ฉันได้ทำในสถานการณ์เหล่านี้ (โดยปกติจะเป็นดีลประเภทการหมดเวลาเซสชันที่พาฉันไปที่หน้าเข้าสู่ระบบ) จะส่งกลับส่วนหัวการตอบกลับที่กำหนดเอง ฉันยังตั้งค่าตัวจัดการ ajax ส่วนกลางที่ตรวจสอบการมีอยู่ของส่วนหัวนั้นและตอบสนองอย่างเหมาะสมเมื่อมีอยู่ (ตัวอย่างเช่นเปลี่ยนเส้นทางทั้งหน้าไปยังหน้าจอเข้าสู่ระบบ)

ในกรณีที่คุณสนใจนี่คือรหัส jQuery ที่ฉันต้องดูสำหรับส่วนหัวที่กำหนดเอง:

/* redirects main window when AJAX request indicates that the session has expired on the backend. */
function checkSession(event, xhr, ajaxOptions)
{
    if (xhr.readyState == 4)
    {
        if(xhr.getResponseHeader("Login-Screen") != null && xhr.getResponseHeader("Login-Screen").length)
        {
            window.location.href='sessionExpired.html'; //whatever
        }
    }
}

$(document).ajaxComplete(checkSession)

1
ขอบคุณฉันเดาว่าฉันจะต้องใช้แนวทางที่คล้ายกันวิเคราะห์การตอบสนอง
Jørgen

11

ฉันพบคุณสมบัติเพื่อตรวจสอบว่าสายของคุณถูกเปลี่ยนเส้นทางหรือไม่ มันคือ xhr.state (): ถ้ามัน "ถูกปฏิเสธ" การเปลี่ยนเส้นทางก็เกิดขึ้น

ตัวอย่างที่มีการโทรกลับสำเร็จ:

request.success(function(data, textStatus, xhr)
{
    if(xhr.state() == "resolved")
    {
        //no redirection
    }
    if(xhr.state() == "rejected")
    {
        //redirection
    }
});

ตัวอย่างที่มีข้อผิดพลาดในการโทรกลับ:

request.error(function(xhr, textStatus)
{
    if (xhr.state() == "rejected")
    {
        //redirection
        location.href = "loginpage";
    } else
    {
        //some other error happened
        alert("error");
    }
});

1
เคล็ดลับในคำตอบของคุณช่วยให้เราทำงานได้จริง เพื่อประโยชน์ของบันทึกย่อที่จะช่วยเหลือผู้อื่นเรามี WebSphere Portal ที่มีการรักษาความปลอดภัยรวมกับ SiteMinder เรามีพอร์ตเล็ตที่ต้องการ Ajax เรียกไปยัง URL ทรัพยากรและเมื่อหมดเวลามันจะมีการเปลี่ยนเส้นทางแบบโปร่งใสเกิดขึ้น แต่เราไม่สามารถจัดการกับวิธีเปลี่ยนเส้นทางไปยังหน้าล็อกอินได้ การตรวจสอบ jqXHR.state () ว่า "ถูกปฏิเสธ" ช่วยได้อย่างแน่นอน ขอบคุณมากอีกครั้ง
Uresh Kuruhuri

การค้นพบที่ยอดเยี่ยมอย่างไรก็ตามอาจมีผลบวกที่ผิดพลาดเนื่องจากสถานะ "ปฏิเสธ" สามารถเรียกใช้ได้แม้ว่าคำสัญญาจะถูกปฏิเสธและไม่ใช่แค่การเปลี่ยนเส้นทาง jQuery อธิบายเมื่อสถานะ "ถูกปฏิเสธ" ถูกส่งapi.jquery.com/deferred.state
Nitin

1

ฉันไม่สามารถเพิ่มภูมิปัญญาเชิงลึกของผู้เขียนโค้ดคนก่อน ๆ ที่ตอบกลับไปได้ แต่ฉันจะเพิ่มกรณีเฉพาะที่คนอื่นอาจพบว่ามีประโยชน์ที่จะรู้

ฉันเจอการเปลี่ยนเส้นทางแบบเงียบ 302 นี้ในบริบทของ SharePoint ฉันมีรหัสไคลเอนต์ Javascript แบบง่ายๆที่ส่ง Ping ไปยังไซต์ย่อยของ SharePoint และหากได้รับการตอบสนอง 200 HTTP มันจะย้ายไปยังไซต์นั้นผ่านทางwindow.location. หากได้รับสิ่งอื่นใดจะแจ้งให้ผู้ใช้ทราบว่าไม่มีไซต์ดังกล่าว

อย่างไรก็ตามในกรณีที่ไซต์มีอยู่ แต่ผู้ใช้ไม่มีสิทธิ์ SharePoint จะเปลี่ยนเส้นทางไปยังเพจ AccessDenied.aspx โดยไม่โต้ตอบ SharePoint ได้ทำการจับมือการพิสูจน์ตัวตน HTTP 401 ที่ระดับเซิร์ฟเวอร์ / ฟาร์มแล้ว - ผู้ใช้สามารถเข้าถึง SharePoint ได้ แต่การเข้าถึงไซต์ย่อยได้รับการจัดการฉันคิดว่าโดยใช้แฟล็กฐานข้อมูลบางประเภท การเปลี่ยนเส้นทางแบบเงียบจะข้ามประโยค "else" ของฉันดังนั้นฉันจึงไม่สามารถโยนข้อผิดพลาดของตัวเองได้ ในกรณีของฉันนี่ไม่ใช่ตัวหยุดการแสดง แต่เป็นพฤติกรรมที่คาดเดาได้อย่างสม่ำเสมอ แต่มันน่าแปลกใจเล็กน้อยและฉันได้เรียนรู้บางอย่างเกี่ยวกับคำขอ HTTP ในกระบวนการ!


1

ฉันสนใจในสิ่งเดียวกันและไม่พบstate()วิธีการที่Takman กล่าวถึงและทำการขุดหาตัวเองเล็กน้อย เพื่อประโยชน์ของผู้คนที่หันมาค้นหาคำตอบนี่คือสิ่งที่ฉันค้นพบ:

ตามที่ระบุไว้หลายครั้งคุณไม่สามารถป้องกันการเปลี่ยนเส้นทางได้ แต่คุณสามารถตรวจพบได้ ตามMDNคุณสามารถใช้responseURLของXMLHttpRequestObjectซึ่งจะมี URL สุดท้ายที่ตอบกลับมาหลังจากเปลี่ยนเส้นทางทั้งหมด มีข้อแม้เพียงอย่างเดียวคือ Internet Explorer ไม่รองรับ (Edge มี) เนื่องจากxhr/ jqXHRส่งผ่านไปยังฟังก์ชันsuccess/ doneของ jquery เป็นส่วนขยายของจริงXMLHttpRequestจึงควรมีอยู่ที่นั่นด้วย


0

ฉันคิดว่าคุณได้รับการตอบกลับ 200 ครั้งเนื่องจากครั้งที่สองไม่มีการเปลี่ยนเส้นทางเนื่องจากหน้า 404 ไม่หมดอายุจะถูกบันทึกไว้ในแคช กล่าวคือเป็นครั้งที่สองที่เบราว์เซอร์ให้หน้าในแคช มีคุณสมบัติ "cache" ใน ajax jquery http://api.jquery.com/jQuery.ajax/

คุณควรเขียนเป็น "เท็จ"


0

แม้ว่าจะไม่สามารถปิดใช้งานการเปลี่ยนเส้นทางตำแหน่งตามในXmlHttpRequestsได้ แต่เมื่อใช้fetch () :

fetch('url', {redirect: manual});

Fetch จะไม่บอกคุณว่า URL ที่เปลี่ยนเส้นทางคืออะไร คุณสามารถปิดใช้งานลักษณะการทำงานได้ แต่ "redirect: manual" ไม่ได้มีไว้เพื่อให้ผู้ใช้จัดการกับการเปลี่ยนเส้นทางที่ตัวเองมีชื่อ intents
lcjury

-2

ฉันไม่แน่ใจว่าจะใช้ได้กับกรณีของคุณหรือไม่ แต่คุณสามารถเขียนโค้ดเพื่อตอบสนองต่อรหัสสถานะเฉพาะในฟังก์ชัน AJAX -

$.ajax({
    url: '/admin/secret/data',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    statusCode: {
        200: function (data) {
            alert('302: Occurred');
            // Bind the JSON data to the UI
        },
        401: function (data) {
            alert('401: Occurred');
            // Handle the 401 error here.
        }
    }
});

9
ฉันไม่คิดว่าจะใช้ได้เพราะ OP บอกว่าเขาได้รับรหัสสถานะ 200 เสมอเนื่องจากการเปลี่ยนเส้นทางเกิดขึ้นในเบื้องหลัง ..
ใช่แบร์รี่

-4

ในส่วนหัวของคำขอในกรณีของคำขอ ajax คุณจะมีสิ่งต่อไปนี้

X-Requested-With    XMLHttpRequest

ตามเกณฑ์นี้ทางฝั่งเซิร์ฟเวอร์คุณสามารถกรองคำขอได้


เขาต้องการตรวจสอบการตอบสนองไม่ใช่คำขอ (ซึ่งเขามีอำนาจควบคุมอยู่แล้ว)
Yes Barry

บางที Gfox แนะนำว่าสำหรับคำขอ ajax ที่ส่งคืน 3xx นั้นไม่มีจุดหมายคุณสามารถกรองคำขอประเภทนี้และส่งคืน 403 ได้เช่นกัน เมื่อคุณมีเว็บไซต์ที่ให้บริการหน้าที่ต้องมีการตรวจสอบความถูกต้องของแบบฟอร์มและหน้าเหล่านั้นก็ทำการโทรด้วย ajax และคุณต้องการใส่ตรรกะการให้สิทธิ์ไว้ในที่เดียวสำหรับฉันแล้วมันเป็นคำตอบที่ถูกต้อง
maciejW
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.