顯示具有 Apex 標籤的文章。 顯示所有文章
顯示具有 Apex 標籤的文章。 顯示所有文章

2017-11-05

Salesforce Secured Callout

在應用系統介接時,使用 Web API 是目前常見的手段;Salesforce 也提供這樣的模式,無論是扮演 service provider (使用內建的 SOAP Web Services,或是自訂 RESTful API),或是 service consumer,都有對應的支援;其中當 Salesforce 扮演 service consumer 時,最常見的是使用 Apex 自行呼叫外部 Web API,這種呼叫模式在 Saleforce 中稱為 callout。

在安全性方面,系統介接時一般會優先討論連線方面的安全性,更嚴謹的才會觸及資料面的安全性;這邊我們只討論前者,也就是透過 TLS 對 HTTP 加密,這樣的外部呼叫稱為 secured callout。

值得注意的是:Salesforce 在實作 secured callout 時,對簽發 target service 憑證的 CA 只認可正向表列中 root CA 簽發的憑證 [1] [2],然而這份列表有些陳舊 [3],許多常見的 root CA 都不在列表中,例如 TWCA Global Root CA,若 target service 不是自有的服務,無法變更憑證時,可能會被迫使用未加密的 HTTP。

另外在 protocol 版本上,Salesforce 支援 TLS 1.1 與 1.2 [4],TLS 1.0 由於可降階至 SSL 3.0 且 SSL 3.0 設計上有安全性缺陷,因此目前已停用 TLS 1.0 [5]

除了 secured callout 外,另一個會使用到憑證的場合是:使用 Salesforce 實作自訂的網站,並掛上自家的網域名稱;這時候對於憑證的限制比前者稍微放寬,允許不是由 root CA 直接簽發的憑證。管理者可以新增所需的 intermediate CA 到 Salesforce [6],但根源的 root CA 仍必須是列表中認可的。

至於新增 custom site 憑證到 Salesforce 時,由於這邊扮演的是 service provider,因此上傳的資訊中必須包括 private key;使用的檔案格式是 Java KeyStore,這方面的基礎知識可以參考 [7]

see also:
[1] Outbound Messaging SSL CA Certificates
[2] Know More about All the SSL Certificates That Are Supported by Salesforce
[2] Salesforce Community Idea: Manage List of Trusted Certificate Authorities 
[3] Summer '15 Release Notes: Test and Use Advanced Networking Protocols
[4] Salesforce Disabling TLS 1.0
[6] SSL Certificate Standards
[8] Making Authenticated Web Service Callouts Using Two-Way SSL

2017-10-24

Apex Serialize Objects to XML

先前的文章 [1] 中提到,Salesforce 的 REST 同時支援兩種輸出格式,XML 與 JSON;client 可以透過 HttpRequst header 中 Accept 屬性指定想要的 content type;這兩個 serialization 的過程對於 REST service 的實作者而言是完全 transparent 的,意即實作時 method 並不 return string 型別,而是直接 return sObject,由系統的 outbound messaging 機制直接處理掉。

然而對於 Apex 開發者而言,程式語言級別對 XML 與 JSON 在 serialization 的支援度就差很遠。以 JSON 為例,無論物件多複雜,要轉成 JSON string 只要一行 JSON.serialize() 就可以搞定 [2],但是轉成 XML string 時,無論使用 XmlStreamWriter [3] 或 DOM.XmlNode [4] [5] 都需要針對物件中各個 fields 作繁瑣地處理。

為了達到快速生成 XML 字串,我們可以透過 (1) 實作一 REST service;(2) 在 Apex 中呼叫該 service,並將 HttpRequest Accept header 設定為 'application/xml' 的方式,快速從 HttpResponse.getBody() 取得 outbound messaging 生成好的 XML 字串。

概念上是走 loopback invocation 的方式,利用既有的機制,寫最少的程式,完成任務。

see also:
[1] Salesforce RESTful Services: Response Content-Type
[2] JSON Support: Roundtrip Serialization and Deserialization
[3] XML Support: Writing XML Using Streams
[4] XML Support: Reading and Writing XML Using the DOM
[5] XmlNode Class
[6] Salesforce Trailblazer Community Idea: Convert Object to XML (Serialize)

2017-10-06

Apex Describe Information

Salesforce 針對 SObject 與 field 分別提供相關的 describe information (a.k.a. metadata),有點類似 Java 中的 java.lang.reflect.Type 與 java.lang.reflect.Field;不過 Salesforce 進一部拆分成 token 與 describe result,前者為一個 compile-time generated & runtime immutable reference,沒有細部資料,但可用於比對 (==),而後者才是真正具備細部資料的結構。

  • Token 轉換至 describe result 的行為稱之為 describe,呼叫 getDescribe() method,可視為 dereference & data loading。
  • SObject 與 field 的 token 與 describe result 資料型別與相關取用方式分別為:
下圖為 4 種 describe information 的產生與轉換方式:
  • 除了 SObject 的 token 與 describe result 有機會從 instance 取得,其餘都必須在 Apex code 中指定 SObject 或 Field name 才能獲得。
  • 不只 SObject instance 有提供 getSObjectType() method,其它提供此 method 的還包括:SObject Describe Result, List 與 Map;其中 List 與 Map 呼叫 getSObjectType() 時等同於針對其 element instance 呼叫該 method。

see also:
[1] Apex Developer Guide: Schema Class
[2] Apex Developer Guide: Schame Namespace
[3] Apex Developer Guide: Dynamic Apex

2017-09-28

Salesforce Apex REST

REST 是目前實作 web API 時較為普遍的選擇,Salesforce 原生在 APEX 中也提供了這方面的支援,方便開發者自訂 API 作為系統整合使用。在 APEX 有以下 6 個 REST annotations:
  1. @RestResource
  2. @HttpDelete
  3. @HttpGet
  4. @HttpPatch
  5. @HttpPost
  6. @HttpPut
值得注意的是:APEX REST annotations 中只有 RestResource 才有 urlMapping 參數,且該 annotation 為 class level;換言之:
  • 每一個 service implementation class,針對各種 HTTP requests 類型只能有 1 個 method;不能同時宣告多個 @HttpGet methods 在 1 class 中;
  • Service implementation class 中的 class name 並不會浮現在 URL 中。
see also:
[1] Apex REST Annotations
[2] Creating REST APIs using Apex REST