الگوی بد: دسترسی نادرست به سرصفحه‌های HTTP چندارزشی در «پروکسی API»

درحال مشاهده اسناد Apigee Edge هستید.
به اسناد Apigee X بروید.
اطلاعات

سرایندهای HTTP جفت‌های نام-مقدار هستند که به برنامه‌های کارخواه و سرویس‌های زیرینه اجازه می‌دهند اطلاعات اضافی درباره درخواست‌ها و پاسخ‌ها را به‌ترتیب ارسال کنند. چند مثال ساده:

  • سرایند درخواست مجوز اطلاعات اعتباری کاربر را به سرور ارسال می‌کند:
    Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
  • سرایند Content-Type نوع محتوای درخواست/پاسخ ارسالی را نشان می‌دهد:
    Content-Type: application/json

«سرفصل‌های HTTP» بسته به تعاریف فیلد سرایند می‌تواند یک یا چند مقدار داشته باشد. سرصفحه چندمقداری دارای مقادیر جداشده با کاما خواهد بود. در اینجا چند نمونه از سرایندهایی که حاوی چندین مقدار هستند آورده شده است:

  • Cache-Control: no-cache, no-store, must-revalidate
  • Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
  • X-Forwarded-For: 10.125.5.30, 10.125.9.125

‫Apigee Edge به توسعه‌دهندگان امکان می‌دهد بااستفاده از متغیرهای جریان در هریک از خط‌مشی‌های Edge یا جریان‌های شرطی به‌راحتی به سرایندها دسترسی پیدا کنند. در اینجا فهرست متغیرهایی که می‌توان از آن‌ها برای دسترسی به سرایند درخواست یا پاسخ خاص در Edge استفاده کرد آمده است:

متغیرهای جریان:

  • message.header.header-name
  • request.header.header-name
  • response.header.header-name
  • message.header.header-name.N
  • request.header.header-name.N
  • response.header.header-name.N

اشیاء جاوا اسکریپت:

  • context.proxyRequest.headers.header-name
  • context.targetRequest.headers.header-name
  • context.proxyResponse.headers.header-name
  • context.targetResponse.headers.header-name

در اینجا نمونه‌ای از خط‌مشی «تخصیص پیام» نشان داده شده است که نحوه خواندن مقدار سرایند درخواست و ذخیره کردن آن در متغیر را نشان می‌دهد:

<AssignMessage continueOnError="false" enabled="true" name="assign-message-default">
  <AssignVariable>
    <Name>reqUserAgent</Name>
    <Ref>request.header.User-Agent</Ref>
  </AssignVariable>
</AssignMessage>

الگوی بد

دسترسی به مقادیر سرایندهای HTTP در خط‌مشی‌های Edge به‌گونه‌ای که فقط مقدار اول را برمی‌گرداند نادرست است و اگر سراینده(های) HTTP خاص بیش‌از یک مقدار داشته باشد می‌تواند باعث بروز مشکل شود.

بخش‌های زیر شامل نمونه‌هایی از دسترسی به سرایند است.

مثال ۱: خواندن سرایند Accept چندارزشی بااستفاده از کد جاوا اسکریپت

درنظر بگیرید که سرصفحه Accept چندین مقدار دارد، همان‌طور که در زیر نشان داده شده است:

Accept: text/html, application/xhtml+xml, application/xml

در اینجا کد جاوا اسکریپت که مقدار را از سرصفحه Accept می‌خواند آمده است:

// Read the values from Accept header
var acceptHeaderValues = context.getVariable("request.header.Accept");

کد جاوا اسکریپت بالا فقط اولین مقدار را از سرایند Accept برمی‌گرداند، مثل text/html.

مثال ۲: خواندن سرایند چندارزشی Access-Control-Allow-Headers در خط‌مشی AssignMessage یا RaiseFault

درنظر بگیرید که سرصفحه Access-Control-Allow-Headers چندین مقدار دارد، همان‌طور که در زیر نشان داده شده است:

Access-Control-Allow-Headers: content-type, authorization

در اینجا بخشی از کد از تنظیم خط‌مشی AssignMessage یا RaiseFault وجود دارد که سرصفحه Access-Control-Allow-Headers را تنظیم می‌کند:

<Set>
  <Headers>
    <Header name="Access-Control-Allow-Headers">{request.header.Access-Control-Request-Headers}</Header>
  </Headers>
</Set>

کد بالا «سرایند» Access-Control-Allow-Headers را فقط با اولین مقدار از سرایند درخواست Access-Control-Allow-Headers تنظیم می‌کند، در این مثال content-type.

تأثیر

  1. در هر دو مثال بالا، توجه داشته باشید که فقط اولین مقدار از سرایندهای چند مقداری برگردانده می‌شود. اگر این مقادیر متعاقباً توسط خط‌مشی دیگری در جریان «پراکسی API» یا توسط سرویس زیرینه برای انجام برخی‌از توابع یا منطق استفاده شوند، ممکن است به نتیجه یا پیامد غیرمنتظره‌ای منجر شود.
  2. وقتی مقادیر سرایند درخواست دردسترس قرار می‌گیرد و به سرور هدف منتقل می‌شود، درخواست‌های API ممکن است به‌طور نادرست توسط زیرینه پردازش شوند و درنتیجه نتایج نادرستی ارائه دهند.
  3. اگر برنامه مشتری به مقادیر سرصفحه خاصی از پاسخ Edge وابسته باشد، ممکن است به‌درستی پردازش نکند و نتایج نادرستی ارائه دهد.

روال مطلوب

  1. از متغیرهای جریان داخلی مناسب استفاده کنید: request.header.header_name.values.count، request.header.header_name.N، response.header.header_name.values.count، response.header.header_name.N.

    سپس با تکرار کردن، همه مقادیر را از سرایند خاصی در خط‌مشی‌های برون‌برد جاوا اسکریپت یا جاوا واکشی کنید.

    مثال: کد نمونه جاوا اسکریپت برای خواندن سرایند چندارزشی

    for (var i = 1; i <=context.getVariable('request.header.Accept.values.count'); i++)
    {
      print(context.getVariable('request.header.Accept.' + i));
    }

    برای مثال، application/xml;q=0.9, */*;q=0.8 به‌عنوان یک مقدار با کد بالا نشان داده خواهد شد.

    اگر مقادیر سرایند باید بااستفاده از نقطه‌ویرگول به‌عنوان جداکننده تقسیم شوند، از string.split(";") برای جدا کردن آن‌ها به مقادیر استفاده کنید.

  2. از تابع substring() در متغیر جاری‌سازی request.header.header_name.values در خط‌مشی RaiseFault یا AssignMessage برای خواندن همه مقادیر سرایند خاص استفاده کنید.

    مثال: خط‌مشی نمونه «افزایش خطا» یا «تخصیص پیام» برای خواندن سرایند چندارزشی

    <Set>
      <Headers>
       <Header name="Access-Control-Allow-Headers">{substring(request.header.Access-Control-Request-Headers.values,1,-1)}</Header>
      </Headers>
    </Set>

مطالعه بیشتر