הדף הזה רלוונטי ל-Apigee ול-Apigee Hybrid.
לעיון במסמכי התיעוד של
Apigee Edge
בנושא הזה מוסבר על מודל האובייקטים של JavaScript ב-Apigee. חשוב להבין את המודל הזה אם אתם מתכוונים להשתמש במדיניות JavaScript כדי להוסיף JavaScript מותאם אישית ל-API Proxy.
מידע על מודל האובייקטים של JavaScript
מודל האובייקטים של JavaScript מגדיר אובייקטים עם מאפיינים משויכים שזמינים לקוד JavaScript שמופעל בזרימת שרת proxy של Apigee. משתמשים במדיניות JavaScript כדי לצרף את הקוד המותאם אישית הזה לזרימת proxy ל-API.
לאובייקטים שמוגדרים על ידי המודל הזה יש היקף בתוך זרימת ה-proxy ל-API, כלומר, אובייקטים ומאפיינים מסוימים זמינים רק בנקודות ספציפיות בזרימה. כשקוד ה-JavaScript מופעל, נוצר היקף להפעלה. במסגרת ההיקף הזה, נוצרים הפניות לאובייקטים הבאים:
- context: אובייקט שמספק גישה להקשר של ההודעה
- request: קיצור דרך שמאפשר גישה לאובייקט הבקשה
- response: קיצור דרך שמאפשר גישה לאובייקט התגובה
- crypto: מספקת פונקציות גיבוב שונות
- print: פונקציה להפקת פלט
- properties: מאפשר גישת קריאה למאפייני ההגדרה במדיניות
אובייקט ההקשר
לאובייקט context יש היקף גלובלי. היא זמינה בכל מקום בתהליך של שרת ה-proxy של ה-API. יש לו ארבעה אובייקטים צאצאים: proxyRequest, proxyResponse, targetRequest ו-targetResponse. האובייקטים המשניים האלה מוגבלים לבקשה ולתשובה הסביבתיות, כלומר לבקשה ולתשובה של השרת הפרוקסי או לבקשה ולתשובה של היעד. לדוגמה, אם מדיניות JavaScript מופעלת בחלק של נקודת הקצה של ה-proxy בתהליך, האובייקטים context.proxyRequest ו-context.proxyResponse נמצאים בהיקף. אם קוד ה-JavaScript מופעל בתהליך יעד, האובייקטים context.targetRequest ו-context.targetResponse נמצאים בהיקף.
לאובייקט context יש גם מאפיינים ושיטות, שמתוארים בפירוט בנושא הזה. לדוגמה, בדוגמת קוד ה-JavaScript הבאה נעשה שימוש במאפיין context.flow ומופעלות השיטות get/setVariable() ב-context.
if (context.flow=="PROXY_REQ_FLOW") { var username = context.getVariable("request.formparam.user"); context.setVariable("USER.name", username); }
השיטות האלה פועלות ישירות על משתני זרימה.
ערך המאפיין context.flow הוא היקף הזרימה הנוכחי. בתהליך הבקשה של ה-proxy, הערך מוגדר לקבוע PROXY_REQ_FLOW. אם בתהליך התגובה של היעד, הערך מוגדר ל-TARGET_RESP_FLOW. הקבוע הזה שימושי להרצת קוד ספציפי להיקף. הפונקציה getter מאפשרת לקבל משתני זרימה, והפונקציה setter מאפשרת להגדיר משתני זרימה. המשתנים האלה זמינים בדרך כלל בתהליך של ה-proxy, ואפשר להשתמש בהם במדיניות אחרת.
פרטים נוספים ודוגמאות זמינים במאמר הפניה לאובייקט ההקשר.
אובייקט הקריפטו
אובייקט הקריפטו מוסיף תמיכה קריפטוגרפית בסיסית ובעלת ביצועים גבוהים למודל האובייקט של JavaScript. פרטים נוספים ודוגמאות מופיעים במאמר הפניה לאובייקט crypto.
אובייקטים של בקשות ותגובות
האובייקטים request ו-response הם הפניות בקיצור לבקשה ולתגובה הסביבתיות, כלומר לבקשה ולתגובה של השרת הפרוקסי או לבקשה ולתגובה של היעד. האובייקטים שהמשתנים האלה מפנים אליהם תלויים בהקשר שבו מופעלת מדיניות JavaScript. אם קוד ה-JavaScript מופעל בתהליך של נקודת קצה של שרת proxy, המשתנים request ו-response מתייחסים אל context.proxyRequest ואל context.proxyResponse. אם קוד ה-JavaScript מופעל בזרימת יעד, המשתנים
מתייחסים אל context.targetRequest וcontext.targetResponse.
הפונקציה print()
מודל האובייקט של JavaScript כולל פונקציה print() שאפשר להשתמש בה כדי להפיק מידע לניפוי באגים בכלי לניפוי באגים של Apigee. מידע נוסף זמין במאמר בנושא ניפוי באגים באמצעות הצהרות JavaScript print().
אובייקט המאפיינים
כשמשתמשים ברכיב Properties בהגדרת המדיניות, קוד ה-JavaScript יכול לגשת לערכים של המאפיינים האלה באמצעות המשתנה properties.
לדוגמה, אם הגדרתם JavaScript עם הקוד הבא:
<Javascript name='JS-1' > <Properties> <Property name="number">8675309</Property> <Property name="firstname">Jenny</Property> </Properties> <ResourceURL>jsc://my-code.js</ResourceURL> </Javascript>
אחר כך ב-my-code.js, תוכלו:
print(properties.firstname); // prints Jenny print(properties.number); // 8675309
מבחינה מעשית, ההגדרה יכולה לאפשר לקוד להתנהג בצורה שונה כשהוא מופעל בסביבות שונות, ברגעים שונים או מכל סיבה אחרת.
לדוגמה, בדוגמה הבאה מצוינים 'שם המשתנה' וסגנון הפלט שבו ה-JavaScript צריך להפיק מידע:
<Javascript name='JS-2' > <Properties> <Property name="output">my_output_variable</Property> <Property name="prettyPrint">true</Property> </Properties> <ResourceURL>jsc://emit-results.js</ResourceURL> </Javascript>
emit-results.js, הקוד יכול לבצע את הפעולות הבאות:
var result = { prop1: "something", prop2 : "something else" } ; if (properties.prettyPrint == "true") { context.setVariable(properties.output, JSON.stringify(result, null, 2)); } else { context.setVariable(properties.output, JSON.stringify(result)); }
הפניה לאובייקט קריפטו
אובייקט ההצפנה מאפשר לכם לבצע פונקציות גיבוב קריפטוגרפיות בסיסיות ב-JavaScript.
לאובייקט הקריפטו יש היקף גלובלי. היא זמינה בכל מקום בתהליך של proxy ל-API. הספרייה Crypto מאפשרת לכם לעבוד עם אובייקטים של hash:
- SHA-1
- SHA256
- SHA512
- MD5
עבודה עם אובייקטים של SHA-1
אפשר ליצור אובייקטים מסוג SHA-1, לעדכן אותם ולהמיר אותם לערכים הקסדצימליים ולערכי base64.
יצירת אובייקט חדש של SHA-1
var _sha1 = crypto.getSHA1();
עדכון אובייקט SHA-1
תחביר
_sha1.update(value);
פרמטרים
- value – (מחרוזת) כל ערך מחרוזת.
דוגמה
עדכון אובייקט SHA-1:
_sha1.update("salt_value"); _sha1.update("some text");
החזרת אובייקט SHA-1 כמחרוזת הקסדצימלית
var _hashed_token = _sha1.digest();
החזרת אובייקט SHA-1 כמחרוזת base64
var _hashed_token = _sha1.digest64();
עבודה עם אובייקטים מסוג SHA-256
אתם יכולים ליצור אובייקטים מסוג SHA-256, לעדכן אותם ולהמיר אותם לערכי הקסדצימליים ו-base64.
יצירת אובייקט SHA-256 חדש
var _sha256 = crypto.getSHA256();
עדכון של אובייקט SHA-256
תחביר
_sha256.update(value);
פרמטרים
- value – (מחרוזת) כל ערך מחרוזת.
דוגמה
עדכון אובייקט SHA-256:
_sha256.update("salt_value"); _sha256.update("some text");
החזרת אובייקט SHA-256 כמחרוזת הקסדצימלית
var _hashed_token = _sha256.digest();
החזרת אובייקט SHA-256 כמחרוזת base64
var _hashed_token = _sha256.digest64();
עבודה עם אובייקטים מסוג SHA-512
אפשר ליצור אובייקטים מסוג SHA-512, לעדכן אותם ולהמיר אותם לערכי הקסדצימליים ולערכי Base64.
יצירת אובייקט חדש של SHA-512
var _sha512 = crypto.getSHA512();
עדכון אובייקט SHA-512
תחביר
_sha512.update(value);
פרמטרים
- value – (מחרוזת) כל ערך מחרוזת.
דוגמה
עדכון אובייקט SHA-512:
_sha512.update("salt_value"); _sha512.update("some text");
החזרת אובייקט SHA-512 כמחרוזת הקסדצימלית
var _hashed_token = _sha512.digest();
החזרת אובייקט SHA-512 כמחרוזת בקידוד Base64
var _hashed_token = _sha512.digest64();
עבודה עם אובייקטים מסוג MD5
אתם יכולים ליצור אובייקטים של MD5, לעדכן אותם ולהמיר אותם לערכי הקסדצימליים ולערכי Base64.
יצירת אובייקט MD5 חדש
var _md5 = crypto.getMD5();
עדכון אובייקט MD5
תחביר
_md5.update(value);
פרמטרים
- value – (מחרוזת) כל ערך מחרוזת.
דוגמה
עדכון אובייקט MD5:
_md5.update("salt_value"); _md5.update("some text");
החזרת אובייקט MD5 כמחרוזת הקסדצימלית
var _hashed_token = _md5.digest();
החזרת אובייקט MD5 כמחרוזת base64
var _hashed_token = _md5.digest64();
תמיכה בתאריך ובשעה של קריפטו
אובייקט ההצפנה תומך בתבניות עיצוב של תאריך ושעה.
crypto.dateFormat()
מחזירה תאריך בפורמט מחרוזת.
תחביר
crypto.dateFormat(format, [timezone], [time])
פרמטרים
- format – (מחרוזת) ההטמעה הבסיסית של הפרמטר הזה היא java.text.SimpleDateFormat. לדוגמה: 'YYYY-MM-DD HH:mm:ss.SSS'
- timezone – (מחרוזת, אופציונלי) ההטמעה הבסיסית של הפרמטר הזה היא java.util.TimeZone. הפרמטר הזה זהה לפרמטר Default: UTC
- time – (מספר, אופציונלי) ערך של חותמת זמן של מערכת Unix לפורמט. ברירת מחדל: השעה הנוכחית
דוגמאות
קבלת השעה הנוכחית, עד לרמת אלפיות השנייה:
var _now = crypto.dateFormat('YYYY-MM-DD HH:mm:ss.SSS');
לראות מה השעה לפי שעון החוף המערבי:
var _pst = crypto.dateFormat('YYYY-MM-DD HH:mm:ss.SSS','PST');
קבלת הערך של עשר שניות מעכשיו:
var _timeNow = Number(context.getVariable('system.timestamp')); var tenSeconds = crypto.dateFormat('YYYY-MM-DD HH:mm:ss.SSS','PST', _timeNow + 10 * 1000);
דוגמאות נוספות. אפשר לעיין גם במאמרי העזרה בנושא java.text.SimpleDateFormat.
var _pst = crypto.dateFormat('M');
var _pst = crypto.dateFormat('EEE, d MMM yyyy HH:mm:ss Z');
var _pst = crypto.dateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
חתימה על מסמכי SOAP באמצעות WS-Security עם אישורי X.509
מאבטחים מסמכי SOAP באמצעות חתימות דיגיטליות, באמצעות WS-Security עם מפתחות RSA ואישורי X.509.
crypto.wsSecRsaSign()
הפונקציה חותמת על מסמך ה-SOAP ומחזירה את מטען הנתונים החתום.
תחביר
crypto.wsSecRsaSign(payload, options)
פרמטרים
- payload – (מחרוזת) מסמך SOAP לחתימה.
- options – (אובייקט) אפשרויות הגדרה לחתימה הדיגיטלית. בטבלה הבאה מפורטות אפשרויות ההגדרה הזמינות. כל ערכי האפשרויות יכולים להיות מחרוזות מילוליות או תבניות של הודעות, שמסומנות באמצעות התווים של התבנית
'{'ו-'}'.שם חובה? תיאור certificateחובה אישור שתואם למפתח הפרטי בפורמט PEM. private_keyחובה משתנה Flow שמכיל את המפתח הפרטי בפורמט PEM. c14_inclusive_elementsאופציונלי רשימה מופרדת בפסיקים של מזהי URI של מרחבי שמות (לא קידומות) שמשמשים להוספת רכיב InclusiveElementsלרכיבCanonicalizationMethod.confirmationאופציונלי אחת מהאפשרויות הבאות: - רשימה של ערכי חתימה ברכיבי
SignatureConfirmationשצריך לחתום עליהם. אם לא קיים רכיבSignatureConfirmationעם הערך שצוין, הוא יתווסף. \*all\*מחרוזת שמציינת שכל רכיביSignatureConfirmationקיימים במסמך המקור ייחתמו.- מחרוזת ריקה שמציינת להוסיף רכיב
ריק.
SignatureConfirmation
elements-to-sign.digest_methodאופציונלי אלגוריתם של סיכום יומי. הערכים התקינים הם sha1אוsha256. ברירת המחדל היאsha256.ds_prefixאופציונלי מחרוזת פשוטה שתשמש כקידומת למרחב השמות. elements_to_signאופציונלי מערך של ביטויי XPath לרכיבים לחתימה (לדוגמה, ["soapenv:Body"]).expiryאופציונלי ערכים להוספה לרכיב ExpiresשלTimestamp. מזינים ערכים כמו 120s, 10m ו-4d כדי לציין 120 שניות, 10 דקות ו-4 ימים. ברירת המחדל היא ללא תפוגה.ignore_security_header_placementאופציונלי ערך בוליאני שקובע אם לבדוק את המיקום של כותרת Securityקיימת במטען הייעודי (payload) הלא חתום. האפשרות הזו מסופקת לצורך תאימות למערכות מדור קודם מסוימות. לא מומלץ להגדיר את הערךtrueכי הוא עלול לחשוף את ה-API שלכם להתקפות של עטיפת חתימה. ברירת המחדל היאfalse.issuer_name_styleאופציונלי הפורמט של שם המנפיק. הערכים התקינים הם CNאוDN.key_identifier_typeאופציונלי מציין את הדרך שבה המסמך החתום מקודד מידע על המפתח ששימש לחתימת המסמך. הערכים התקפים הם BST_DIRECT_REFERENCE,ISSUER_SERIAL,RSA_KEY_VALUE,THUMBPRINTו-X509_CERT_DIRECT. בדוגמאות הבאות אפשר לראות את הצורה של רכיבKeyInfoלסוגים שונים של מזהי מפתחות. ברירת המחדל היאBST_DIRECT_REFERENCE.private_key_passwordאופציונלי מפתח הסיסמה, אם המפתח הפרטי מוצפן. signing_methodאופציונלי השיטה שבה נעשה שימוש לחתימה. הערכים התקינים הם rsa-sha1אוrsa-sha256. ערך ברירת המחדל הואrsa-sha1, אבל מומלץ מאוד להגדיר את הערךrsa-sha256.soap_versionאופציונלי גרסת SOAP. הגרסאות התקינות הן 1.1 ו-1.2. ברירת המחדל היא 1.1. transform_inclusive_elementsאופציונלי רשימה מופרדת בפסיקים של מזהי URI של מרחבי שמות (לא קידומות) שמשמשים להוספת רכיב InclusiveElementsלרכיבTransform. - רשימה של ערכי חתימה ברכיבי
דוגמאות
X509_CERT_DIRECT
var reqPayload = context.getVariable("request.content"); var signed = crypto.wsSecRsaSign(reqPayload,{ private_key: '{private.key.pem}', certificate: '{public.cert.pem}', // elements_to_sign: 'wsa:Timestamp, soap:Body', signing_method: 'rsa-sha256', digest_method: 'sha256', key_identifier_type: 'X509_CERT_DIRECT', expiry: '120s' }); var resPayload_signed = context.setVariable("request.content", signed);
בדוגמה שלמעלה אפשר לראות איך חותמים על מסמך SOAP עם מזהה מפתח מסוג X509_CERT_DIRECT. הוא מניח שהמפתח הפרטי והאישור נטענו למשתני זרימה.
במסמך החתום שיוצא יופיע רכיב KeyInfo שנראה כך:
<KeyInfo> <!-- xmlns="http://www.w3.org/2000/09/xmldsig#" --> <X509Data> <X509Certificate>MIIEKjCCAxKgAwIBAgI....</X509Certificate> </X509Data> </KeyInfo>
BST_DIRECT_REFERENCE
var reqPayload = context.getVariable("request.content"); var signed = crypto.wsSecRsaSign(reqPayload,{ private_key: '{private.key.pem}', certificate: '{public.cert.pem}', // elements_to_sign: 'wsa:Timestamp, soap:Body', signing_method: 'rsa-sha256', digest_method: 'sha256', key_identifier_type: 'BST_DIRECT_REFERENCE', expiry: '120s' }); var resPayload_signed = context.setVariable("request.content", signed);
בדוגמה שלמעלה אפשר לראות איך חותמים על מסמך SOAP עם מזהה מפתח מסוג BST_DIRECT_REFERENCE. הוא מניח שהמפתח הפרטי והאישור נטענו למשתני זרימה.
במסמך החתום שיוצא יופיע רכיב KeyInfo שנראה כך:
<KeyInfo> <!-- xmlns="http://www.w3.org/2000/09/xmldsig#" --> <wssec:SecurityTokenReference> <wssec:Reference URI="#ST-101" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/> </wssec:SecurityTokenReference> </KeyInfo>
יהיה עוד רכיב שיוצב בכותרת WS-Security, באמצעות wsu:Id מרכיב KeyInfo שלמעלה, שיספק את האישור שקודד כ-BinarySecurityToken:
<wssec:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="ST-101">MIIEKjCCAxKgAwIB... </wssec:BinarySecurityToken>
ISSUER_SERIAL
var reqPayload = context.getVariable("request.content"); var signed = crypto.wsSecRsaSign(reqPayload,{ private_key: '{private.key.pem}', certificate: '{public.cert.pem}', // elements_to_sign: 'wsa:Timestamp, soap:Body', signing_method: 'rsa-sha256', digest_method: 'sha256', key_identifier_type: 'ISSUER_SERIAL', expiry: '120s' }); var resPayload_signed = context.setVariable("request.content", signed);
בדוגמה שלמעלה אפשר לראות איך חותמים על מסמך SOAP עם מזהה מפתח מסוג ISSUER_SERIAL. הוא מניח שהמפתח הפרטי והאישור נטענו למשתני זרימה.
במסמך החתום שיוצא יופיע רכיב KeyInfo שנראה כך:
<KeyInfo> <!-- xmlns="http://www.w3.org/2000/09/xmldsig#" --> <wssec:SecurityTokenReference wsu:Id="STR-102"> <X509Data> <X509IssuerSerial> <X509IssuerName>CN=Test,O=Test,L=Test,ST=Test,C=US</X509IssuerName> <X509SerialNumber>1234567890</X509SerialNumber> </X509IssuerSerial> </X509Data> </wssec:SecurityTokenReference> </KeyInfo>
THUMBPRINT
var reqPayload = context.getVariable("request.content"); var signed = crypto.wsSecRsaSign(reqPayload,{ private_key: '{private.key.pem}', certificate: '{public.cert.pem}', // elements_to_sign: 'wsa:Timestamp, soap:Body', signing_method: 'rsa-sha256', digest_method: 'sha256', key_identifier_type: 'THUMBPRINT', expiry: '120s' }); var resPayload_signed = context.setVariable("request.content", signed);
בדוגמה שלמעלה אפשר לראות איך חותמים על מסמך SOAP עם מזהה מפתח מסוג THUMBPRINT. הוא מניח שהמפתח הפרטי והאישור נטענו למשתני flow.
במסמך החתום שיוצא יופיע רכיב KeyInfo שנראה כך:
<KeyInfo> <!-- xmlns="http://www.w3.org/2000/09/xmldsig#" --> <wssec:SecurityTokenReference wsu:Id="STR-102"> <wssec:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security1.1#ThumbprintSHA1">XP+3...</wssec:KeyIdentifier> </wssec:SecurityTokenReference> </KeyInfo>
אימות מסמכי SOAP חתומים באמצעות WS-Security עם אישורי X.509
מאמת את החתימה הדיגיטלית של מסמך SOAP באמצעות WS-Security עם RSA/X.509. Apigee מבצע אימות כדי לוודא שהארגומנטים שהועברו תקפים.
crypto.wsSecRsaValidate()
מאמת את החתימה הדיגיטלית של מסמך SOAP.
תחביר
crypto.wsSecRsaValidate(payload, options)
פרמטרים
- payload – (מחרוזת) מסמך SOAP עם חתימה דיגיטלית לאימות.
- options – (אובייקט) אפשרויות הגדרה לאימות. בטבלה הבאה מפורטות אפשרויות ההגדרה הזמינות. כל ערכי האפשרויות יכולים להיות מחרוזות מילוליות או תבניות של הודעות, שמסומנות באמצעות התווים של התבנית
'{'ו-''}'.שם חובה? תיאור accept_subject_cnsאופציונלי רשימה מופרדת בפסיקים של שמות נפוצים (CN) של הנושא, שהם חותמים קבילים. אם חתימה כלשהי היא מ-CN שלא תואם לאף אחד מה-CN שצוינו, האימות ייכשל. accept_thumbprintsאופציונלי רשימה מופרדת בפסיקים של טביעות אצבע של אישורי SHA-1 של חותמים קבילים. אם חתימה כלשהי היא מאישור עם טביעת אצבע שלא תואמת לאחת מטביעות האצבע שצוינו, האימות נכשל. צריך לציין רק אחד מהמאפיינים accept-thumbprintsאוaccept-thumbprints-sha256. צריך לספק לפחות אחת מהאפשרויות האלה אם לא מספקים את האפשרותcertificate.accept_thumbprints_sha256אופציונלי רשימה של טביעות אצבע SHA-256 של האישורים שהמערכת מקבלת כחתימות. הרשימה מופרדת בפסיקים. אם חתימה כלשהי היא מאישור עם טביעת אצבע שלא תואמת לאחת מטביעות האצבע שצוינו, האימות נכשל. צריך לציין רק אחד מהמאפיינים accept-thumbprintsאוaccept-thumbprints-sha256. צריך לספק לפחות אחת מהאפשרויות האלה אם לא מספקים את האפשרותcertificate.certificateאופציונלי אישור שמספק את המפתח הציבורי לאימות החתימה. חובה ומשמש רק אם KeyInfoלא מספק באופן מפורש את האישור במסמך החתום.digest_methodאופציונלי שיטת הגיבוב הנתמכת. הערכים התקינים הם sha1אוsha256. אם לא מציינים את השיטה, המערכת לא בודקת אותה.ignore_certificate_expiryאופציונלי ערך בוליאני שקובע אם להתעלם מתאריכי התוקף של האישור שסופק. היא שימושית לבדיקות. ברירת המחדל היא false.ignore_expiryאופציונלי ערך בוליאני שמציין אם להתעלם מהשדה Timestamp/Expiresכשמעריכים את התוקף של מסמך ה-SOAP. ברירת המחדל היאfalse.ignore_security_header_placementאופציונלי ערך בוליאני שמציין אם לבדוק את המיקום של כותרת האבטחה במטען הייעודי החתום. האפשרות הזו מסופקת לצורך תאימות למערכות מדור קודם מסוימות. לא מומלץ להגדיר את הערך הזה ל- trueכי הוא עלול לחשוף ממשקי API להתקפות של עטיפת חתימות. ברירת המחדל היאfalse.issuer_name_dn_comparisonאופציונלי השיטה שבה משתמשים כדי לקבוע אם שני שמות של מנפיקים מתייחסים לאותו גורם. ההגדרה הזו רלוונטית רק אם המסמך החתום כולל את KeyInfoשעוטף אתX509IssuerSerialוissuer-name-styleהואDN(ברירת המחדל). הערך יכול להיות אחד מהערכים הבאים: {string,normal,reverse,unordered}. ברירת המחדל היאstring.issuer_name_dn_comparison_exclue_numeric_oidsאופציונלי השיטה שבה משתמשים כדי לקבוע אם שני שמות המנפיקים מתייחסים לאותה ישות. ההגדרה הזו חלה רק אם המסמך החתום כולל את התג KeyInfoשמקיף את התגX509IssuerSerial, והערך של התגissuer-name-styleהואDN(ברירת המחדל), והערך של התגissuer-name-dn-comparisonהואnormal, reverseאוunordered.issuer_name_styleאופציונלי הפורמט של שם המנפיק. התג הזה משמש רק אם המסמך החתום כולל KeyInfoשעוטף אתX509IssuerSerial. הערכים התקינים כולליםCNאוDN.max_lifetimeאופציונלי משך החיים המקסימלי של המסמך החתום. מזינים ערך כמו 120s, 10m ו-4d כדי לציין 120 שניות, 10 דקות ו-4 ימים. כדי להשתמש באפשרות הזו, צריך לכלול ב- TimestampרכיבCreatedורכיבExpires. ברירת המחדל היא ללא משך חיים מקסימלי.require_expiryאופציונלי ערך בוליאני שקובע אם נדרש תאריך תפוגה בחותמת הזמן. מומלץ להשאיר את הערך הזה על true. ברירת המחדל היאtrue.required_sign_elementsאופציונלי רשימה של טפסים מופרדים בפסיקים או ברווחים prefix:Tagשמציינת את הרכיבים שצריך לחתום עליהם. ברירת המחדל היאsoap:Body, wsu:Timestamp. כדי לדרוש רק חתימה על חותמת הזמן ולא על גוף ההודעה במהלך האימות, צריך להגדיר את הערךwsu:Timestamp. כדי לדרוש רק חתימה בגוף ולא חותמת זמן במהלך האימות, צריך להגדיר את הערךsoap:Body. הקידומת והתג תלויים באותיות רישיות. מומלץ להשאיר את הערך הזה כברירת המחדל, אלא אם יש לכם סיבה ספציפית לשנות אותו.signing_methodאופציונלי שיטת החתימה שחייבת להיות זהה לשיטת החתימה במסמך החתום. הערכים התקינים הם rsa-sha1אוrsa-sha256. אם לא מציינים את השיטה, המערכת לא בודקת את שיטת החתימה.
דוגמאות
אישור מוטמע
var reqPayload = context.getVariable("request.content"); var isValid = crypto.wsSecRsaValidate(reqPayload, { accept_thumbprints_sha256: '2578afd28d1d16e6b8f1d3ddfd5be4ff683dd147afae8d7096c183309794bbd9', signing_method: 'rsa-sha256', digest_method: 'sha256' }); if (!isValid) { throw "invalid" }
בדוגמה שלמעלה מוצג אופן האימות של מסמך SOAP שנחתם כך שבלוק החתימה מכיל אישור בתוך רכיב KeyInfo. אם השתמשתם בפונקציה crypto.wsSecRsaSign() של Apigee כדי לחתום על המסמך, והשתמשתם ב-key_identifier_type של X509_CERT_DIRECT או ב-BST_DIRECT_REFERENCE, התוצאה תהיה הטמעה של אישור בבלוק החתימה, ואפשר להשתמש בקוד שמוצג למעלה כדי לאמת אותו. מערכות אחרות
ייצרו גם מסמכים חתומים עם אישורים מוטמעים, ותוכלו לאמת את החתימות האלה גם בדרך הזו.
כדי שהאימות יצליח, צריך לספק רשימה של טביעות אצבע של אישור מהימן אחד או יותר. בלי זה, Apigee יאמת את החתימה, אבל לא יוודא שהחותם מהימן.
אישור שסופק באופן חיצוני
var reqPayload = context.getVariable("request.content"); var isValid = crypto.wsSecRsaValidate(reqPayload, { certificate: '{public.cert.pem}', signing_method: 'rsa-sha256', digest_method: 'sha256' }); if (!isValid) { throw "invalid" }
בדוגמה שלמעלה מוצג אופן האימות של מסמך SOAP שנחתם כך שבלוק החתימה לא מכיל אישור בתוך רכיב KeyInfo, אלא מכיל הפניה לאישור, בצורה של מספר סידורי ושם המנפיק, או טביעת אצבע. אם השתמשתם בפונקציה Apigee crypto.wsSecRsaSign() כדי לחתום על המסמך, והשתמשתם ב-key_identifier_type של ISSUER_SERIAL או THUMBPRINT, התוצאה תהיה שהאישור לא יוטמע בבלוק החתימה. במקרה כזה, לוגיקת האימות צריכה לספק את האישור כמו שמוצג בדוגמת הקוד. מערכות אחרות גם ייצרו מסמכים חתומים ללא אישורים מוטמעים, ותוכלו לאמת את החתימות האלה גם בדרך הזו.
כשמספקים את האישור באופן מפורש, לא צריך לספק רשימה של טביעות אצבע של אישורים מהימנים. אם מספקים את האישור באופן מפורש, מניחים שיש אמון באישור.
משתמשים ב-getHash() כדי לקבל אחד מאובייקטי הגיבוב הנתמכים
דוגמאות
var _hash1 = crypto.getHash('MD5'); var _hash2 = crypto.getHash('SHA-1'); var _hash3 = crypto.getHash('SHA-256'); var _hash4 = crypto.getHash('SHA-512');
דוגמה עם קריפטו
try { // get values to use with hash functions var salt = context.getVariable("salt") || 'SomeHardCodedSalt'; var host = context.getVariable("request.header.Host"); var unhashedToken = ""; var _timeNow = Number(context.getVariable('system.timestamp')); var now = crypto.dateFormat('YYYY-MM-DD HH:mm:ss.SSS','PST', _timeNow); unhashed_token = "|" + now + "|" + host // generate a hash with the unhashedToken: var sha512 = crypto.getSHA512(); sha512.update(salt); sha512.update(unhashedToken); // convert to base64 var base64Token = sha512.digest64(); // set headers context.setVariable("request.header.now", now); context.setVariable("request.header.token", base64Token); } catch(e) { throw 'Error in Javascript'; }
הפניה לאובייקט ההקשר
אובייקט context נוצר לכל עסקה של בקשה/תגובה שמופעלת על ידי proxy ל-API. האובייקט context חושף שיטות לקבלת משתנים שקשורים לכל עסקה, להגדרתם ולהסרתם.
משתנים מגדירים מאפיינים ספציפיים לעסקה. השעה ביום, הלוקאל של הלקוח ששולח את הבקשה, הסוכן המשתמש של הלקוח ששולח את הבקשה וכתובת ה-URL של שירות היעד הם דוגמאות למשתנים שזמינים ב-context. לכן, context שימושי לבניית לוגיקה שמסתמכת על המאפיינים האלה כדי להפעיל התנהגות מותאמת אישית.
אפשר לעיין בהפניה למשתני Flow ובמדיניות ExtractVariables.
context object summary
בטבלה הזו מופיע תיאור קצר של אובייקט ההקשר ושל אובייקטי הצאצא שלו, ורשימה של המאפיינים שקשורים לכל אחד מהם.
| שם | תיאור | מאפיינים |
|---|---|---|
context |
רכיב wrapper להקשר של צינור עיבוד ההודעות ולזרימות של הבקשה והתגובה שמופעלות על ידי ProxyEndpoint ו-TargetEndpoint. | flow, session |
context.proxyRequest |
אובייקט שמייצג את הודעת הבקשה הנכנסת ל-ProxyEndpoint (מהאפליקציה ששולחת את הבקשה ל-proxy ל-API) | כותרות, פרמטרים של שאילתות, שיטה, גוף, כתובת URL |
context.targetRequest |
אובייקט שמייצג את הודעת הבקשה לדואר יוצא מ-TargetEndpoint (מ-proxy ל-API לשירות לקצה העורפי). | כותרות, פרמטרים של שאילתות, שיטה, גוף, כתובת URL |
context.targetResponse |
אובייקט שמייצג את הודעת התגובה של היעד לדואר נכנס (מהשירות לקצה העורפי ל-proxy ל-API) | כותרות, תוכן, סטטוס |
context.proxyResponse |
אובייקט שמייצג את הודעת התגובה של השרת Proxy היוצא (מ-proxy ל-API לאפליקציה ששלחה את הבקשה) | כותרות, תוכן, סטטוס |
context.flow |
השם של התהליך הנוכחי. | ראו context.flow. |
context.session |
מיפוי של צמדי שם/ערך שאפשר להשתמש בהם כדי להעביר אובייקטים בין שני שלבים שונים שמופעלים באותו הקשר. לדוגמה: context.session['key'] = 123. |
מידע נוסף על מקרים שבהם כדאי להשתמש באובייקט הזה ומקרים שבהם לא כדאי מופיע במאמר מה ההבדל בין context.session['hello'] = {} לבין context.setVariable("hello", {}). |
שיטות של אובייקט context
context.getVariable()
מאחזרת את הערך של משתנה מוגדר מראש או משתנה מותאם אישית.
תחביר
context.getVariable("variable-name");
דוגמה
כדי לקבל את הערך לשנה הנוכחית:
var year = context.getVariable('system.time.year');
context.setVariable()
הפונקציה מגדירה את הערך של משתנה מותאם אישית או של משתנים מוגדרים מראש שניתנים לכתיבה.
תחביר
context.setVariable("variable-name", value);
דוגמה
תרחיש נפוץ להגדרת משתנה הוא כשצריך לכתוב באופן דינמי את כתובת ה-URL של היעד ב-proxy ל-API. הסקריפט הבא של JavaScript מקבל את הערך של משתנה שנקרא USER.name, מוסיף את הערך הזה כפרמטר של שאילתה לכתובת ה-URL
http://mocktarget.apigee.net?user=, ואז מגדיר את הערך הזה ל-target.url המוגדר מראש.
context.setVariable("target.url", "http://mocktarget.apigee.net/user?user="+context.getVariable("USER.name"));
context.removeVariable()
הסרת משתנה מההקשר.
תחביר
context.removeVariable('variable-name');
מאפייני אובייקט ההקשר
המאפיין flow הוא מחרוזת שמזהה את התהליך הנוכחי של ה-proxy ל-API. המאפיין הזה משמש לציון ה-Flow שאליו מצורף ה-JavaScript. הערכים הנתמכים הם:
PROXY_REQ_FLOWPROXY_RESP_FLOWTARGET_REQ_FLOWTARGET_RESP_FLOW
כל שם של Flow כולל את PreFlow, PostFlow וכל Flows מותנה שמוגדר ב-ProxyEndpoint(s) או ב-TargetEndpoint(s).
המאפיין האופציונלי הזה שימושי כשקוד JavaScript משותף מופעל ביותר מ-Flow אחד, אבל יכול להיות שההתנהגות שלו תשתנה בהתאם ל-Flow שבו הוא מופעל. משתמשים במאפיין Flow עבור מודולים של JavaScript שמיועדים לשימוש חוזר בכמה פרוקסי של API, שבהם הקוד נדרש כדי לבדוק את Flow הנוכחי לפני הפעלת הלוגיקה.
דוגמה
הגדרת כותרת HTTP רק ב-targetRequest Flow:
if (context.flow=="TARGET_REQ_FLOW") { context.targetRequest.headers['TARGET-HEADER-X']='foo'; }
הגדרת התוכן רק ב-proxyResponse Flow:
if (context.flow=="PROXY_RESP_FLOW") { context.proxyResponse.content='bar'; }
מיפוי של זוגות שם/ערך שאפשר להשתמש בהם כדי להעביר אובייקטים בין שתי מדיניות שמופעלות באותו הקשר של הודעה.
דוגמה
הגדרת ערך בסשן:
context.session['key'] = 123;
קבלת הערך מהסשן:
var value = context.session['key']; // 123
context object children
כפי שמוצג בהמשך, Flow מלא של proxy ל-API כולל ארבעה שלבים נפרדים, שלכל אחד מהם משויך אובייקט הודעה שהוא צאצא של אובייקט ההקשר:
-
context.proxyRequest: ההודעה של הבקשה הנכנסת שהתקבלה מהלקוח ששלח את הבקשה. -
context.targetRequest: הודעת הבקשה לדואר יוצא שנשלחה לשירות הקצה העורפי. -
context.proxyResponse: הודעת התגובה היוצאת שמוחזרת ללקוח ששלח את הבקשה. -
context.targetResponse: הודעת הבקשה לדואר נכנס שהתקבלה משירות הקצה העורפי.

בקטעים הבאים מתוארות השיטות והמאפיינים של האובייקטים האלה:
context.*Request child objects
לכל טרנזקציית HTTP שמופעלת ב-proxy ל-API, נוצרים שני אובייקטים של הודעות בקשה: אחד נכנס (הבקשה מהלקוח) ואחד יוצא (הבקשה שנוצרה על ידי ה-proxy ל-API ונשלחה ליעד העורפי).
לאובייקט context יש אובייקטים צאצאים שמייצגים את הודעות הבקשה האלה:
context.proxyRequest ו-context.targetRequest. האובייקטים האלה מאפשרים לכם לגשת למאפיינים בתהליך הבקשה שנמצאים בהיקף כשקוד ה-JavaScript שלכם מופעל.
context.*Request child object properties
| שם המאפיין | תיאור |
|---|---|
url |
המאפיין כתובת ה-URL המלאה של הבקשה מורכבת מהמאפיינים הבאים:
כשמקבלים
|
|
דוגמאות: context.targetRequest.url = 'http://www.example.com/path?q1=1' context.targetRequest.protocol ='https'; |
|
headers |
כותרות של בקשת HTTP כמיפוי של |
|
דוגמאות: עבור בקשת ה-HTTP הזו: POST /v1/blogs HTTP/1.1 Host: api.example.com Content-Type: application/json Authorization: Bearer ylSkZIjbdWybfs4fUQe9BqP0LH5Z context.proxyRequest.headers['Content-Type']; context.proxyRequest.headers['Authorization']; יחזיר את הערכים הבאים application/json Bearer ylSkZIjbdWybfs4fUQe9BqP0LH5Z |
|
queryParams |
פרמטרים של שאילתת הודעה של הבקשה כמיפוי של |
|
דוגמאות: "?city=PaloAlto&city=NewYork"אפשר לגשת אליהם כ: context.proxyRequest.queryParams['city']; // == 'PaloAlto' context.proxyRequest.queryParams['city'][0] // == 'PaloAlto' context.proxyRequest.queryParams['city'][1]; // == 'NewYork' context.proxyRequest.queryParams['city'].length(); // == 2 |
|
method |
הפועל של HTTP (GET, POST, PUT, DELETE). PATCH וכו') שמשויך לבקשה |
|
דוגמאות: בבקשה הזו: POST /v1/blogs HTTP/1.1 Host: api.example.com Content-Type: application/json Authorization: Bearer ylSkZIjbdWybfs4fUQe9BqP0LH5Z קוד ה-JavaScript הבא: context.proxyRequest.method; יוחזר הערך הבא POST |
|
body |
גוף ההודעה (המטען הייעודי) של בקשת ה-HTTP. גוף הבקשה כולל את המאפיינים הבאים:
|
|
דוגמאות: עבור גוף בפורמט XML: <customer number='1'> <name>Fred<name/> <customer/> כדי לגשת לרכיבים של אובייקט ה-XML, פועלים לפי השלבים הבאים: var name = context.targetRequest.body.asXML.name; כדי לגשת למאפייני XML, משתמשים בסימון var number = context.targetRequest.body.asXML.@number; עבור תוכן בקשת JSON: { "a": 1 , "b" : "2" } var a = context.proxyRequest.body.asJSON.a; // == 1 var b = context.proxyRequest.body.asJSON.b; // == 2 כדי לקרוא פרמטרים של טופס: "vehicle=Car&vehicle=Truck"v0 = context.proxyRequest.body.asForm['vehicle'][0]; v1 = context.proxyRequest.body.asForm['vehicle'][1]; |
context.*Response child objects
לכל טרנזקציית HTTP שמופעלת ב-proxy ל-API, נוצרים שני אובייקטים של הודעות תגובה: אחד נכנס (התגובה משירות לקצה העורפי) ואחד יוצא (התגובה שנשלחת בחזרה ללקוח).
לאובייקט ההקשר יש אובייקטים צאצא שמייצגים את הודעות התגובה האלה:
context.proxyResponse ו-context.targetResponse. האובייקטים האלה מאפשרים לכם לגשת למאפיינים בתהליך התגובה שנמצא בהיקף כשקוד ה-JavaScript שלכם מופעל.
context.*Response object properties
| שם המאפיין | תיאור |
|---|---|
headers |
כותרות ה-HTTP של הודעת התשובה כמיפוי של |
|
דוגמה: var cookie = context.targetResponse.headers['Set-Cookie']; |
|
status |
קוד הסטטוס עם הודעת הסטטוס כמאפיין. גם קוד הסטטוס וגם הודעת הסטטוס זמינים כמאפיינים. |
|
דוגמה: var status = context.targetResponse.status.code; // 200 var msg = context.targetResponse.status.message; // "OK" |
|
content |
גוף ה-HTTP (תוכן המטען הייעודי) של הודעת התגובה. תוכן התגובה כולל את הרכיבים הבאים: context.targetResponse.content.asXML; context.targetResponse.content.asJSON; |
שימוש בסימון .asXML
אפשר להשתמש בסימון .asXML כדי לעבור על מסמך XML.
בקטע הזה מוסבר איך להשתמש בסימון הזה, ומה ההבדל בינו לבין
request.content ו-context.proxyRequest.content.
לדוגמה:
request.content.asXML
או
context.proxyRequest.content.asXML
אפשר להשתמש בטפסים *.content ו-*.content.asXML בהקשר של מחרוזת, ו-JavaScript תכפה עליהם להפוך למחרוזות. במקרה הראשון
(*.content), המחרוזת כוללת את כל ההצהרות וגם הערות XML. במקרה השני (*.content.asXML), ערך המחרוזת של התוצאה עובר ניקוי מהצהרות ומהערות.
דוגמה
msg.content:
<?xml version="1.0" encoding="UTF-8"?> <yahoo:error xmlns:yahoo="http://yahooapis.com/v1/base.rng" xml:lang="en-US"> <yahoo:description>Please provide valid credentials. OAuth oauth_problem="unable_to_determine_oauth_type", realm="yahooapis.com" </yahoo:description> </yahoo:error> <!-- mg023.mail.gq1.yahoo.com uncompressed/chunked Sat Dec 14 01:23:35 UTC 2013 -->
msg.content.asXML:
<?xml version="1.0" encoding="UTF-8"?> <yahoo:error xmlns:yahoo="http://yahooapis.com/v1/base.rng" xml:lang="en-US"> <yahoo:description>Please provide valid credentials. OAuth oauth_problem="unable_to_determine_oauth_type", realm="yahooapis.com" </yahoo:description> </yahoo:error>
בנוסף, אפשר להשתמש בטופס .asXML כדי לעבור בהיררכיית ה-XML, על ידי ציון השמות של רכיבים ומאפיינים. אי אפשר לעבור בהיררכיה באמצעות התחביר השני.
ניפוי באגים באמצעות הצהרות print() ב-JavaScript
אם אתם משתמשים במדיניות JavaScript כדי להריץ קוד JavaScript בהתאמה אישית, תוכלו להשתמש בפונקציה print() כדי להציג מידע לניפוי באגים בכלי לניפוי באגים. הפונקציה הזו זמינה ישירות דרך מודל האובייקטים של JavaScript. לדוגמה:
if (context.flow=="PROXY_REQ_FLOW") { print("In proxy request flow"); var username = context.getVariable("request.queryparam.user"); print("Got query param: " + username); context.setVariable("USER.name", username); print("Set query param: " + context.getVariable("USER.name")); } if (context.flow=="TARGET_REQ_FLOW") { print("In target request flow"); var username = context.getVariable("USER.name"); var url = "http://mocktarget.apigee.net/user?" context.setVariable("target.url", url + "user=" + username); print("Callout to URL: ", context.getVariable("target.url")); }
כדי לראות את הפלט, בוחרים באפשרות פלט מכל העסקאות בתחתית חלון הניפוי באגים. אפשר גם למצוא פלט בנכס הניפוי באגים שנקרא stepExecution-stdout.
ביצוע קריאות ל-JavaScript באמצעות httpClient
אפשר להשתמש ב-httpClient כדי לשלוח כמה בקשות HTTP אסינכרוניות מקבילות לכל כתובת URL מתוך קוד JavaScript מותאם אישית שמופעל בתהליך של proxy ל-API.
אובייקט httpClient נחשף על ידי מודל אובייקט JavaScript של Apigee.
מידע על httpClient
אובייקט httpClient נחשף לקוד JavaScript בהתאמה אישית שפועל ב-Apigee
באמצעות מודל אובייקט JavaScript. כדי לצרף JavaScript בהתאמה אישית ל-proxy ל-API, משתמשים במדיניות JavaScript. כשמריצים את המדיניות, קוד ה-JavaScript המותאם אישית מופעל.
אובייקט httpClient שימושי לפיתוח שירותים מורכבים או mashup. לדוגמה, אפשר לאחד כמה קריאות ל-backend לשיטת API אחת.
זוהי דוגמה בסיסית לדפוסי שימוש. יוצרים מופע של אובייקט Request, מקצים לו כתובת URL (למשל, לשירות backend שרוצים להפעיל), ומפעילים את httpClient.send עם אובייקט הבקשה הזה.
var myRequest = new Request(); myRequest.url = "http://www.example.com"; var exchangeObj = httpClient.send(myRequest);
חומר עזר בנושא httpClient
לקוח ה-HTTP חושף שתי שיטות: get() ו-send().
httpClient.get()
שיטה נוחה לבקשות HTTP פשוטות GET, ללא תמיכה בכותרות HTTP.
שימוש
var exchangeObj = httpClient.get(url);
החזרות
השיטה מחזירה אובייקט exchange. לאובייקט הזה אין מאפיינים, והוא חושף את השיטות הבאות:
-
isError(): (Boolean) מחזירהtrueאם ל-httpClient לא הייתה אפשרות להתחבר לשרת. קודי הסטטוס של HTTP4xxו-5xxמובילים ל-isError()false, כי החיבור הושלם והוחזר קוד תגובה תקין. אם הפונקציהisError()מחזירהtrue, אז קריאה לפונקציהgetResponse()מחזירה את JavaScriptundefined. -
isSuccess(): (Boolean) מחזירהtrueאם השליחה הושלמה בהצלחה. -
isComplete(): (בוליאני) מחזירה את הערךtrueאם הבקשה הושלמה. -
waitForComplete(): השהיית השרשור עד להשלמת הבקשה (בהצלחה או בשגיאה). -
getResponse(): (אובייקט) מחזירה את אובייקט התגובה אם הפעולהhttpClient.send()הושלמה בהצלחה. לאובייקט שמוחזר יש את אותן שיטות ומאפיינים כמו לאובייקט context.proxyResponse. סיכום אובייקט ההקשר -
getError(): (מחרוזת) אם הקריאה אלhttpClient.send()הסתיימה בשגיאה, הפונקציה מחזירה את הודעת השגיאה כמחרוזת.
דוגמה
שליחה של אובייקט Request מוגדר במלואו שמכיל את המאפיינים של בקשת ה-HTTP. משתמשים בקריאה חוזרת לא חוסמת כדי לעבד את התגובה.
// Add the required the headers for making a specific API request var headers = {'X-SOME-HEADER' : 'some value' }; // Make a GET API request along with headers var myRequest = new Request("http://www.example.com","GET",headers); // Define the callback function and process the response from the GET API request function onComplete(response,error) { // Check if the HTTP request was successful if (response) { context.setVariable('example.status', response.status); } else { context.setVariable('example.error', 'Woops: ' + error); } } // Specify the callback Function as an argument httpClient.get(myRequest, onComplete);
שימוש במדיניות JavaScript
משתמשים במדיניות JavaScript כדי לצרף קוד JavaScript בהתאמה אישית לתהליך של שרת proxy. מדיניות JavaScript