Cross Domain AJAX עם flXHR ו-jQuery

הסבר על שימוש בפלאש ו-jQuery כדי לקיים תקשורת עם דומיין אחר.

Same Domain Policy הוא מנגנון אבטחה ב-JavaScript שמונע שליחה וקבלת מידע באמצעות AJAX מדומיינים אחרים. אם אני נמצא בדומיין internet-israel.com למשל, אני לא יכול לשלוח ולקבל מידע באמצעות AJAX מדומיין internet-israel.org.

דרך מצוינת לעקוף את ה-Same Domain Policy היא באמצעות פרוקסי. במאמר נפרד הסברתי איך ליצור פרוקסי מבוסס PHP ולעבוד מולו ב-AJAX. דרך נוספת ואלגנטית יותר היא באמצעות JSONP. במאמר נפרד יש הסבר מקיף כיצד להשתמש ב-JSONP וגם הסבר על השימוש בו ב-jQuery.

פתרון נוסף ושימושי הוא שימוש בטכנולוגית פלאש. למרות שגם פלאש כפוף ל-Same Domain Policy, פלאש מאפשר לכל בעל שרת לקיים תקשורת פלאש אליו באמצעות crossdomain.xml. שימוש בפלאש שישמש כגשר בין הג'אווהסקריפט שלנו לשרת המרוחק, ובתנאי והשרת המרוחק משתמש ב-crossdomain.xml יאפשר לנו לבצע תקשורת AJAX בקלות.

היתרונות בשימוש בפלאש לעומת שיטת JSONP
לשימוש בפלאש כדי לבצע Cross Domain AJAX יש מספר יתרונות רב על השימוש ב-JSONP:
1. יש Error handling.
2. יש אפשרות לבדוק את המידע לפני שמקבלים אותו.
3. לא חייבים להעביר רק JSON אלא כל מידע שהוא.

החסרונות בשימוש בפלאש
1. חייבים להשתמש בפלאש…. בעיה עם אייפונים/אייפודים.
2. צריכים להציב crossdomain.xml באתר שמקבל את הבקשה.

אז איך זה עובד?

יש לנו פקודת JavaScript ששולחת מידע אל הפלאש. הפלאש מקבל את המידע, בודק אם לדומיין המבוקש יש crossdomain.xml ובמידה וכן – שולח את המידע אליו וטוען את התגובה. לאחר טעינת התגובה הוא מעביר את המידע שהתקבל אל ה-JavaScript.

איך עושים את זה?

באופן עקרוני, כל אחד יכול ליצור את הפתרון הזה מאפס, אך זה מחייב ידיעה של ActionScript ולא מעט עבודה. כיום יש מספר פתרונות שעושים את העבודה במקומך. הפתרון המועדף עלי היא flXHR – ספרית JavaScript שדואגת להכל. יש גם פלאגין ל-jQuery.

ראשית, אנו נוריד את flXHR מהאתר שלו ואת הפלגין של jQuery מהדף הזה.

שנית, נכין את צד השרת. צד השרת בדוגמה שלנו הוא ב-PHP אך הוא יכול להיות בכל שפה אחרת. ה-PHP פשוט מאד ובדומה לדוגמה שיש במאמר המדגים על הפרוקסי, הוא מקבל מחרוזת טקסט אנגלית בלבד באמצעות פרמטר myName והופך אותה. אם אני שולח moshe, אני אקבל ehsom.


< ?php
if(ctype_alpha($_REQUEST['myName']))
{
	$string =$_REQUEST['myName'];
	$result = strrev($string);
	print $result;
}
else
{
	die;
}

את קובץ ה-php הזה אני אציב בדומיין אחר. לצורך העניין באתר אחר שלי בשם Numenore. תלחצו על הקישור ותראו בעצמכם.

אחרי כן, אני אקפיד להכניס ל-root שלי את קובץ ה-crossdomain.xml שמתיר לקבצי פלאש לגשת לתיקיה.
שימו לב שאתם מכניסים את הקובץ הזה ל-root!


<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
   <site-control permitted-cross-domain-policies="master-only" />
   <allow-access-from domain="*" />
   <allow-http-request-headers-from domain="*" headers="*" />
</cross-domain-policy>

כדאי מאד להזהר עם ה-xml הזה כיוון שהוא מאפשר לכל קובץ פלאש לגשת אליכם ויוצר חור אבטחה, עדיף להגביל את הדומיינים שניגשים אליו.

עכשיו נתחיל בעבודה. בדף שבו אנו מבצעים את קריאת ה-AJAX לדומיין האחר, אנו צריכים להקפיד שיהיו לנו את הסקריפטים הבאים:


<script type="text/javascript" src="https://internet-israel.com/internet_files/flxhr/flXHR.js"></script>
<script type="text/javascript" src="https://internet-israel.com/scripts/jquery.js"></script>
<script type="text/javascript" src="https://internet-israel.com/internet_files/flxhr/jquery.xhr.js"></script>
<script type="text/javascript" src="https://internet-israel.com/internet_files/flxhr/jquery.flXHRproxy.js"></script>

הסקריפט הראשון הוא אובייקט ה-flXHR שהיה בקובץ שהורדנו. הקובץ השני הוא jQuery והקובץ השלישי והרביעי הם הפלאגינים שגם אותם הורדנו בנפרד. בתיקיה שבה שמתי את flxHR אני שם גם את flXHR.swf ו-flXHRproxy.swf ושאר הקבצים שהגיעו עם flxHR.js.

עכשיו ניגש ליישום. ראשית, עלינו לבצע הגדרה של הקשר ל-flXHR שלנו באמצעות פונקצית jQuery.flXHRproxy.registerOptions שרצה מיד בטעינת הדף. חובה להכניס לפונקציה הזו ארגומנט אחד של ה-url הכללי שאיתו אנו רוצים ליצור קשר ושם ה-crossdomain.xml שלנו. בדוגמא שלנו, אני רוצה ליצור קשר עם www.numenore.com/test וה-crossdomain כבר נמצא שם בשם crossdomain.xml.


	jQuery.flXHRproxy.registerOptions("http://www.numenore.com/test/");

זה חייב לרוץ ב-onready. אחרי כן, אנו צריכים לכתוב את ה-AJAX עצמו. ראשית באמצעות פקודת ajaxSetup אנו נגדיר שני דברים שקריטיים לכל תהליך ה-flXHR: הגדרת transport כ-flXHR והגדרת פונקציה נפרדת שתטפל בשגיאות. זה יותר פשוט ממה שזה נשמע:


		jQuery.ajaxSetup({transport:'flXHRproxy',error:handleError});

כאשר transport:'flXHRproxy', הוא מנדטורי וה-:handleError יכול להיות כל שם של פונקציה. בפונקצית handleError אפשר להגדיר מה לעשות כשיש טעויות – כמו למשל להעלות מסר התנצלות, לשלוח הודעת שגיאה לשרת/אדמינסטרטור וכו' וכו'. פונקצית handleError טובה לפיתוח היא:


function handleError(XHRobj,errtype,errObj) {
	alert("Error: "+errObj.number
		+"\nType: "+errObj.name
		+"\nDescription: "+errObj.description
		+"\nSource Object Id: "+errObj.srcElement.instanceId
	);
}

הפונקציה הזו תדפיס ב-alert פירוט נרחב על כל הודעת שגיאה.

אחרי שהגדרנו את הבקשה שלנו ואף הגדרנו פונקציה שמטפלת בשגיאות. כל מה שנותר לנו לעשות זה לכתוב את הפקודה ששולחת את ה-AJAX והפונקציה שתעבוד במקרה של הצלחה. פונקצית ה-AJAX דומה מאד לכל פונקצית jquery.get או jquery.post שאנו מכירים.


		jQuery.post(
					"http://www.numenore.com/test/cross.php",
					"myName=moshe",
					handleLoading,
					"text/plain"
		);

למי שמכיר AJAX עם jQuery הפונקציה הזו אמורה להיות מוכרת. הארגומנט הראשון הוא היעד שלנו, שהוא קובץ ה-PHP שיצרנו קודם לכן. הארגומנט השני הוא מחרוזת טקסט שאנו שולחים. במקרה הזה זה פרמטר myName ו-moshe. אבל זה יכול להיות כמה פרמטרים או אובייקט JSON שעבר stringify. הארגומנט השלישי הוא handleLoading, הפונקציה שמטפלת בהצלחה והארגומנט הרביעי הוא סוג הנתונים שאנו שולחים.

פונקצית handleLoading היא פשוטה למדי ודומה לכל פונקצית AJAX שהיא:


function handleLoading(data,status,XHRobj) {
	if (status == 'success') {
		alert(data);
	}
}

כל מה שהפונקציה הזו עושה היא להקפיץ alert עם התוצאה. אם הכנסנו moshe, התוצאה צריכה להיות ehsom. והנה הדוגמא המיוחלת:

לחץ כאן להפעלת הדוגמא

והקוד המלא:


jQuery(document).ready(function() {
	jQuery.flXHRproxy.registerOptions("http://www.numenore.com/test/");
	
	$("#activate_flxhr").click(function() {
		doit();
		return false;
	});
});

function doit() {
		jQuery.ajaxSetup({transport:'flXHRproxy',error:handleError});
		jQuery.post(
					"http://www.numenore.com/test/cross.php",
					"myName=moshe",
					handleLoading,
					"text/plain"
		);
	}

 
function handleLoading(data,status,XHRobj) {
	if (status == 'success') {
		alert(data);
	}
}
 
function handleError(XHRobj,errtype,errObj) {
	alert("Error: "+errObj.number
		+"\nType: "+errObj.name
		+"\nDescription: "+errObj.description
		+"\nSource Object Id: "+errObj.srcElement.instanceId
	);
}

התוצאה יכולה להיות כמובן כל תוצאה שהיא – אובייקט JSON, XML – מה שתרצו. ככה מבצעים בקשת cross domain עם פלאש ו-jQuery. באתר של flXHR יש הסברים איך לעבוד עם פריימוורקים נוספים כמו Mootools ו-Dojo. וגם הסבר לעבודה ללא פריימוורק.

פוסטים נוספים שכדאי לקרוא

DALL·E 2023-10-21 22.28.58 - Photo of a computer server room with red warning lights flashing, indicating a potential cyber threat. Multiple screens display graphs showing a sudde
יסודות בתכנות

מבוא לאבטחת מידע: IDOR

הסבר על התקפה אהובה ומוצלחת שבאמצעותה שואבים מידע מאתרים

גלילה לראש העמוד