Mark Hammer's Blog

SalesforceやTrailheadに関する情報を投稿しているブログです。

Web-to-リードフォームに、自動住所入力機能を追加する

SalesforceにはWeb-to-リードという、Webサイトからリードを作成するための機能があります。

このWeb-to-リードを簡単に利用するために、Salesforceにはリードの項目を選択すればその項目を登録するフォームを自動生成する「Web-to-リードフォームの作成」という機能があります。

この「Web-to-リードフォームの作成」機能は各項目を登録するためのテキストボックスを含む簡単なフォームを作成するだけのもので、その他の機能はありません。

今回は、このフォームに自動住所入力機能(郵便番号を入れると自動で住所を入力する機能)を加えてみます。

Web-to-リードフォームに加える項目

今回は、必要最小限と思われる以下項目を追加してみます。

  • メール
  • 会社名
  • 郵便番号
  • 都道府県
  • 市区郡
  • 町名・番地

Web-to-リードフォームが生成するHTMLコード

上記項目を選択した場合に生成されるHTMLコードは以下になります。(コメントアウト部分など、不要な個所は除きます)

<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8">

<form action="https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8" method="POST">

<input type=hidden name="oid" value="00Dxxxxxxxxxxxx">
<input type=hidden name="retURL" value="http://www.google.com">

<label for="last_name">姓</label><input  id="last_name" maxlength="80" name="last_name" size="20" type="text" /><br>

<label for="first_name">名</label><input  id="first_name" maxlength="40" name="first_name" size="20" type="text" /><br>

<label for="email">メール</label><input  id="email" maxlength="80" name="email" size="20" type="text" /><br>

<label for="company">会社名</label><input  id="company" maxlength="40" name="company" size="20" type="text" /><br>

<label for="zip">郵便番号</label><input  id="zip" maxlength="20" name="zip" size="20" type="text" /><br>

<label for="country">国</label><input  id="country" maxlength="40" name="country" size="20" type="text" /><br>

<label for="state">都道府県</label><input  id="state" maxlength="20" name="state" size="20" type="text" /><br>

<label for="city">市区郡</label><input  id="city" maxlength="40" name="city" size="20" type="text" /><br>

<label for="street">町名・番地</label><textarea name="street"></textarea><br>

<input type="submit" name="submit">

</form>

ブラウザから見るとこう見えます。

f:id:mark-hammer:20190507003420p:plain
Web-to-リード画面

自動住所入力機能を追加する

今回は、ajaxzip3を使用して機能を追加してみます。

github.com

まず、ヘッダ部分に

<script src="https://ajaxzip3.github.io/ajaxzip3.js" charset="UTF-8"></script>

を追加します。

次に、「郵便番号」の行を

<label for="zip">郵便番号</label><input id="zip" maxlength="20" name="zip" size="20" type="text" onKeyUp="AjaxZip3.zip2addr(this,'','state','city','street');"/><br>

に変更します。

変更後のHTMLコードは以下になります。

<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8">
<script src="https://ajaxzip3.github.io/ajaxzip3.js" charset="UTF-8"></script>

<form action="https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8" method="POST">

<input type=hidden name="oid" value="00Dxxxxxxxxxxxx">
<input type=hidden name="retURL" value="http://www.google.com">

<label for="last_name">姓</label><input  id="last_name" maxlength="80" name="last_name" size="20" type="text" /><br>

<label for="first_name">名</label><input  id="first_name" maxlength="40" name="first_name" size="20" type="text" /><br>

<label for="email">メール</label><input  id="email" maxlength="80" name="email" size="20" type="text" /><br>

<label for="company">会社名</label><input  id="company" maxlength="40" name="company" size="20" type="text" /><br>

<label for="zip">郵便番号</label><input  id="zip" maxlength="20" name="zip" size="20" type="text" onKeyUp="AjaxZip3.zip2addr(this,'','state','city','street');"/><br>

<label for="country">国</label><input  id="country" maxlength="40" name="country" size="20" type="text" /><br>

<label for="state">都道府県</label><input  id="state" maxlength="20" name="state" size="20" type="text" /><br>

<label for="city">市区郡</label><input  id="city" maxlength="40" name="city" size="20" type="text" /><br>

<label for="street">町名・番地</label><textarea name="street"></textarea><br>

<input type="submit" name="submit">

</form>

f:id:mark-hammer:20190507004733p:plain
機能追加後

おわりに

Web-to-リードフォームで生成されるHTMLコードは非常に単純なため、このまま使用することは推奨できません*1が、「もし生成コードに自動住所入力機能を追加するなら」ということで書いてみました。
参考になれば幸いです。

*1:Web-to-リード作成に必要な組織IDがHTMLソースコードから見えるため、スパムが大量に送られる危険がある

Salesforceでコーディングをしない3つの理由

Twitterのタイムラインを眺めていると、以下のブログ投稿を見かけました。

tyoshikawa1106.hatenablog.com

この投稿を読んで、思うところを書いてみます。

TL; DR

  • 引用したyoshikawa-sanのブログの内容は間違いではないよ。
  • でも、「コーディング導入により発生する考慮点」もあるよ。
  • Apex等の開発機能を使うか決めるときは、「標準機能では必要な機能を満たせないのか」や、「Salesforceの運用にかけられる費用」を考慮した方がいいよ。

はじめに

ここでいう「標準機能」とは、Salesforce.com Inc. における、開発者サポート に含まれない機能をいいます。

具体例

  • 標準機能対象
    • カスタムオブジェクト、カスタム項目
    • プロファイル、ロール、共有ルール
    • ワークフロールール
    • プロセスビルダー
    • レポート、ダッシュボード
  • 標準機能対象外
    • Apexクラス、Apexトリガ
    • Visualforce
    • Lightning Aura Component, Lightning Web Component
    • フロー
    • API

引用したブログについて

内容としては、以下のようなものでした。

  • 「Apex開発やコーディングはやったらダメ」という話があるけど、Apex開発やコーディングを考慮に含めることで、実装可能な機能に幅が広がるよ。
  • ワークフロールール、プロセスビルダーでは手が回らないところを、適切にコーディングすれば実現できるよ。

上記については、まさにその通りだと思います。
ワークフロールールやプロセスビルダーでは、起動条件が複雑な場合の表現が難しく、また項目更新順の指定ができないことから、「特定の順序で項目を更新したい」という希望の実現ができなかったりします。

ただし、Salesforceでの開発は、標準機能のみの利用では考慮する必要がなかった部分を考慮する必要があります。

追加考慮1: Salesforce運用コストの増加

Salesforceの勉強会等でよく聞く悩みに、以下のようなパターンがあります。

  • ケース1
    • 導入時に開発会社にコーディング含む機能開発を依頼した。
    • その後、Salesforceバージョンアップによりコーディング部分が正しく動作しなくなった。
    • 結果、機能変更がないのに追加で費用が発生した。
  • ケース2
    • 導入時に、社内のSalesforce開発者がコーディング含む機能開発を行った。
    • その後、Salesforce開発者が退職したため、何も分からない状況で運用を引き継ぐこととなった。
    • また、Salesforceバージョンアップによりコーディング部分が正しく動作しなくなったため、Salesforceの保守に想定以上の時間を取られている。

これらは標準機能のみ使用した環境でも起こりえますが、以下の理由により、改修に係るコストは一般的にコーディングを行った環境の方が多くなると考えられます。

  • コーディング箇所の改修の場合、当然ながらApex等の開発者スキルが必要になる
  • 問題となっている機能の無効化が簡単にできない(下記「追加考慮2」)
  • Salesforceサポートを使用できないケースが発生する(下記「追加考慮3」)

追加考慮2: 機能無効化のための作業

「トラブルが発生したため、まずは動作を無効化したい」となった場合、ワークフロールール、プロセスビルダーは「無効化」ボタンがあるため、「まずは無効化し、トラブルを止める」ことがだれでも可能です。
一方、Apexクラス、Apexトリガの場合、このナレッジに従い、外部ツールをインストールするところから始める必要があり、「だれでも対応可能」なものではありません。

このように、Salesforceで開発を行った場合、「改修だけではなく、機能無効化も難しい」ことを考慮する必要があります。

追加考慮3: Salesforceサポート範囲の違い

www.salesforce.com

「はじめに」に記載した標準機能の場合、Salesforceサポートではライセンス費用のみで提供されるBasic Success Plan でもサポート対象となります。
一方、開発者サポート の範囲は、追加費用が必要なPremier Success Plan が必要となります。

また、コーディング部分の開発者サポートは、「200行以下」という条件があります。
つまり、「コーディング部分でよく分からないエラーが起きたのでなんとかしてほしい」はもちろん、「1000行程度のApexクラスでエラーが発生したので解決方法を教えてほしい」という問い合わせも対象外になり、「エラー発生個所を200行程度まで絞る」作業が発生します。
このように、トラブル発生時の問い合わせも、ある程度の開発者スキルがないと難しいものになります。

おわりに

「開発機能を使えば、実装可能な機能の幅も広がる。」これについて異論はありません。
しかし、開発機能を使うことで、導入時には見えなかった縛りが発生することも、知っておいて損はないでしょう。

個人的には、Salesforceでコーディングを導入する際は安易に考えず、

  • 標準機能では実装が難しい機能が、業務上必須である。

かつ、

  • 導入、保守まで対応できる開発会社に依頼し、保守分の費用を支払うことができる。
  • または、Premierサポートプランを契約でき、かつ一定以上の開発者スキルを持つ人物が社内に複数おり、「1人辞めたらSalesforce運用が立ち行かなくなる」状況ではない。

という条件を満たすか考慮したうえで決定した方が良いと思います。

おまけ

この投稿では「コーディング導入によって発生するネガティブな面」を主に記載しました。

では、「標準機能を使うメリット」は何か、について資料探しをしたところ、以下のSalesforce公式ブログを見つけました。
標準オブジェクト、標準機能を用いることのメリットについて5つ+おまけの理由が記載されています。

www.salesforce.com

Salesforce導入時にコーディングを導入するか、しないかについては、「コーディング導入による機能の幅の広がり」だけではなく、「コーディング導入によるデメリット」や「標準機能のみを使用するメリット」も知っていただいたうえでご判断いただいた方がいいと考えております。
この投稿がご覧になった方々の参考になれば幸いです。

追記

AppExchange(パッケージ)についてはこの記事を書いているときに頭になかったのですが、

  • パッケージ自体はボタンをクリックすればアンインストール可能(ヘルプ
  • ただし、パッケージインストールで追加したオブジェクトや項目を使ってカスタムオブジェクトやワークフロー、プロセスビルダー等を組み込んだ場合、アンインストール不可
  • パッケージの中には「サポート提供なし」のものも多く、トラブルがあったとしても対応してくれないケースあり(Salesforce Labs提供のパッケージもサポート提供なし)

と、コーディングほどではないにしろ安易に本番環境に導入するのは控えた方がいいものになっています。

もちろん便利な機能を組み込んだパッケージやサポート付きのものもありますので、そのあたりはケースバイケースで利用するものだと思います。

追記2

以下の引用Tweetをいただきました。ありがとうございます。

https://twitter.com/Lefty_Bomberman/status/1125776188540985345

IdeaExchange自体はユーザの声から機能を追加する、いい仕組みなのですが、「7万Point集めても3年以上Updateなし」といったケースもあるので、ステータスが「COMING IN THE NEXT RELEASE」とかになったものを参考にするものがいいのかな、と思います。*1

参考

IdeaExchange の概要とステータスについて

*1:ちなみにSandboxプレビューの後にリリースノートから消された機能も存在します

Trailhead モジュール:Programmatic Development with Custom Metadata Types

※この内容は2019/4時点のものです。

Use Metadata Relationship Fields

https://trailhead.salesforce.com/ja/content/learn/modules/custom_metadata_types_adv/cmt_md_relationships

  • 説明:英語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 以下内容のカスタムメタデータ型を作成してください。
    • 表示ラベル:Service Provider
    • オブジェクト名:Service_Provider
  • 「Service Provider」メタデータ型に、以下カスタム項目を追加してください。
    • データ型:メタデータリレーション
    • 関連先:Entity Definition
    • 項目の表示ラベル:Object Type
    • 項目名:Object_Type
  • 「Service Provider」メタデータ型に、以下カスタム項目を追加してください。
    • データ型:メタデータリレーション
    • 関連先:Field Definition
    • 項目の表示ラベル:Provider Field
    • 制御項目:Object Type
    • 項目名:Provider_Field
  • 「Service Provider」メタデータ型に、以下カスタム項目を追加してください。
    • データ型:メール
    • 項目の表示ラベル:Provider Owner Email
    • 項目名:Provider_Owner_Email

Develop with and Test with Custom Metadata Types

https://trailhead.salesforce.com/ja/content/learn/modules/custom_metadata_types_adv/cmt_develop

  • 説明:英語
  • Challenge:英語選択問題

Protect Custom Metadata Types and Records

https://trailhead.salesforce.com/ja/content/learn/modules/custom_metadata_types_adv/cmt_manageability

  • 説明:英語
  • Challenge:英語選択問題

Package Custom Metadata Types

https://trailhead.salesforce.com/ja/content/learn/modules/custom_metadata_types_adv/cmt_packaging

  • 説明:英語
  • Challenge:英語選択問題

Convert Custom Settings

https://trailhead.salesforce.com/ja/content/learn/modules/custom_metadata_types_adv/cmt_convert

  • 説明:英語
  • Challenge:英語選択問題

Trailhead モジュール:Lightning コンポーネントのセキュリティ

※この内容は2019/4時点のものです。

Lightning セキュリティの使用開始

https://trailhead.salesforce.com/ja/content/learn/modules/security-for-lightning-components/get-started-with-lightning-security

  • 説明:日本語
  • Challenge:日本語選択問題

セキュアな Lightning コンポーネントの作成

https://trailhead.salesforce.com/ja/content/learn/modules/security-for-lightning-components/create-secure-lightning-components

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

このChallengeは、通常のDeveloper Edition組織やTrailhead Playground組織ではなく、Kingdom Management DE組織を使用してください。
このChallengeの前に、Kingdom Management DE組織にサインアップしてください。

  • 「Secure Lightning」アプリケーションの「Secure Component Challenge」タブをクリックしてください。
  • 開発者コンソールを起動し、「LTNG_Secure_Component_Challenge」Lightningコンポーネントを開いてください。
  • 「LTNG_Secure_Component_Challenge」Lightningコンポーネントのコードから、脆弱性がある2か所を修正してください。
  • 「Secure Component Challenge」タブに戻り、検索実行後に表示される説明文にて、ページ動作が変化しないことを確認してください。

Lightning JavaScript コードの保護

https://trailhead.salesforce.com/ja/content/learn/modules/security-for-lightning-components/secure-your-lightning-java-script-code

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

このChallengeは、通常のDeveloper Edition組織やTrailhead Playground組織ではなく、Kingdom Management DE組織を使用してください。
このChallengeの前に、Kingdom Management DE組織にサインアップしてください。

  • 開発者コンソールを開き、secureFilters という名前で MIME タイプが text/javascript の静的リソースを新規作成し、このファイルをアップロードしてください。
  • 開発者コンソールを起動し、「LTNG_SecureFilters_Challenge」Lightningコンポーネントコントローラを開き、「secureFilters」静的リソースを使用してユーザデータをエンコードしてください。
  • 「Secure Lightning」アプリケーションの「SecureFilters Challenge」タブをクリックし、動作を確認してください。
  • ヒント:ユーザデータはHTML要素に変換されるため、それに合わせた適切なエンコード機能を使用してください。

コンポーネント通信の保護

https://trailhead.salesforce.com/ja/content/learn/modules/security-for-lightning-components/secure-your-component-communication

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

このChallengeは、通常のDeveloper Edition組織やTrailhead Playground組織ではなく、Kingdom Management DE組織を使用してください。
このChallengeの前に、Kingdom Management DE組織にサインアップしてください。

  • 「Secure Lightning」アプリケーションの「Access Control Challenge」タブをクリックしてください。
  • 開発者コンソールを起動し、「LTNG_Access_Control_Challenge_Wrapper」、「LTNG_Access_Control_Challenge」Lightningコンポーネントコントローラを開いてください。
  • 内部管理用属性が他のコンポーネントに公開されないよう、属性のアクセスレベルを変更してください。
  • 「Access Control Challenge」タブに戻り、動作を確認してください。
  • ヒント:一部の属性は公開されることを意図した作りになっています。しかし、王国(Kingdom Management DE組織)のためのアクセス制御を考えると、属性のアクセスレベルをコンポーネント内に保つことが常に最善です。

Trailhead モジュール:アプリケーションロジックの脆弱性防止

※この内容は2019/4時点のものです。

オープンリダイレクトの概要

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_application_logic_vulnerabilities/secdev_app_logic_open_redirect

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「Open Redirect」アプリケーションの「Open Redirect Basics Challenge」タブをクリックしてください。
  • 表示されたVisualforceページにてリダイレクト機能を見つけ、外部のWebサイト(例:https://www.google.com )にリダイレクトさせてください。
  • オープンリダイレクト攻撃が成功したら、「Challengeを確認して500ポイントを獲得」ボタンをクリックしてください。

標準のオープンリダイレクト防止の概要

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_application_logic_vulnerabilities/secdev_app_logic_standard_open_redirect

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「Open Redirect」アプリケーションの「Standard Redirect Protections Challenge」タブをクリックしてください。
  • 表示されたVisualforceページにてリダイレクト機能を見つけ、外部のWebサイト(例:https://www.google.com )にリダイレクトさせてください。
  • オープンリダイレクト攻撃が成功したら、「Challengeを確認して500ポイントを獲得」ボタンをクリックしてください。

コード内のオープンリダイレクトの防止

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_application_logic_vulnerabilities/secdev_app_logic_preventing_open_redirect

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「Open Redirect」アプリケーションの「Prevent Open Redirect Challenge」タブをクリックしてください。
  • 「Apex Controller」リンクをクリックし、ローカルリダイレクトのみ強制する方法でオープンリダイレクトを防止するようsave()関数を修正してください。

クロスサイトリクエストフォージェリ (CSRF) の防止

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_application_logic_vulnerabilities/secdev_app_logic_csrf

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「Cross-Site Request Forgery (CSRF)」アプリケーションの「CSRF Challenge」タブをクリックしてください。
  • 「Apex Controller」リンクをクリックし、「CSRF_Challenge」Visualforce ページからアクションハンドラを削除してください。
  • 「Approval Action (NO CSRF)」がある行にて、以下内容の変更を行ってください。
    • アクションに「{!approveReqNOCSRF}」を設定した「<apex:commandlink>」タグを追加してください。このメソッドは既にApexコントローラに追加されています。
    • <apex:commandlink>」タグの中に、value を「{!req.id}」、assignTo を「{!approve}」とした「<apex:param>」タグを追加してください。

クリックジャックの防止

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_application_logic_vulnerabilities/secdev_app_logic_clickjacking

  • 説明:日本語
  • Challenge:日本語選択問題

セキュアではないリモートリソースのやりとりの防止

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_application_logic_vulnerabilities/secdev_app_logic_insecure_remote_resource

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「Insecure Remote Resources」アプリケーションの「Insecure Remote Resource Challenge」タブをクリックしてください。
  • 「Visualforce Page」リンクをクリックし、セキュアではないリモートリソースが使用されている2箇所について、静的リソース(Challenge_Resourcesというzip形式のフォルダ)を参照する差し込み項目に差し替えてください。

Trailhead モジュール:Platform アプリケーションビルダー認定資格の更新 (Spring '19)

※この内容は2019/4時点のものです。

アプリケーション構築者向けの新機能の学習

https://trailhead.salesforce.com/ja/content/learn/modules/platform-app-builder-maintenance-spring19/learn-whats-new-for-appbuilders

  • 説明:日本語
  • Challenge:日本語選択問題

カスタマイズされたホームページとコンポーネントを使ってみる

https://trailhead.salesforce.com/ja/content/learn/modules/platform-app-builder-maintenance-spring19/get-hands-on-with-customized-home-pages-and-components

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 新しいTrailhead Playground組織を起動してください。
    • 起動時にエラーになる場合は、数分待ってから再度起動してください。Trailhead Playground組織が読み込まれるまでに最大15分かかることがあります。
  • 以下内容で、新規Lightningページを作成してください。
    • 「ホームページ」を選択
    • 表示ラベル:Sales Home Page
    • テンプレート:標準ホームページ
  • 以下の標準コンポーネントを追加してください。
    • リッチテキスト
    • Chatter フィード
    • アシスタント
    • 今日の行動
    • 今日のToDo
  • 「リッチテキスト」コンポーネントに以下を設定してください。
    • テキストに「Welcome!」を追加してください。
    • フォントを「Salesforce Sans」に設定してください。
  • 「リッチテキスト」コンポーネントで、コンポーネントの表示を設定するためのフィルタを以下の通り追加してください。
    • 項目:権限>標準権限>Lightning Experience ユーザ
    • 演算子:等号
    • 値:True
  • Lightningページを保存、有効化し、組織のデフォルトとして割り当ててください。

Trailhead モジュール:アドミニストレーター認定資格の更新 (Spring '19)

※この内容は2019/4時点のものです。

Spring '19 の新機能の学習

https://trailhead.salesforce.com/ja/content/learn/modules/administrator-maintenance-spring19/learn-whats-new-in-spring19

  • 説明:日本語
  • Challenge:日本語選択問題

Lightning ページを使ってみる

https://trailhead.salesforce.com/ja/content/learn/modules/administrator-maintenance-spring19/get-hands-on-with-account-teams

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 新しいTrailhead Playground組織を起動してください。
    • 起動時にエラーになる場合は、数分待ってから再度起動してください。Trailhead Playground組織が読み込まれるまでに最大15分かかることがあります。
  • 以下内容で、新規Lightningページを作成してください。
    • 「レコードページ」を選択
    • 表示ラベル:Account Management
    • オブジェクト:取引先
    • テンプレート:「Salesforceのデフォルトページをコピー」をクリックし、「デフォルトの取引先レコードページ」をクリック
    • 「完了」をクリック
  • ページのテンプレートを、「ヘッダー、サブヘッダー、左サイドバー」に変更してください。
    • 「テンプレート領域を対応付け」画面では、設定をそのままとして「完了」をクリックしてください。
  • 以下の標準コンポーネントを追加してください。
    • トピック
    • 最近使ったデータ
  • Lightningページを保存、有効化し、組織のデフォルトとして割り当ててください。

Trailhead モジュール:Platform デベロッパー資格の更新 (Spring '19)

※この内容は2019/4時点のものです。

Spring '19 での Platform デベロッパー向けの新機能の学習

https://trailhead.salesforce.com/ja/content/learn/modules/platform-developer1-maintenance-spring19/learn-whats-new-for-platform-developers-sp19

  • 説明:日本語
  • Challenge:日本語選択問題

新しい Apex セキュリティ設定の使用

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「ハンズオン Challenge への準備」節に記載の通り、「Secret Key」カスタムテキスト項目を取引先責任者オブジェクトに作成してください。
  • 新規Apexクラス「SecureApexRest」を作成してください。
  • 「ハンズオン Challenge への準備」節の「SecureApexRest」コードをコピーし、「SecureApexRest」Apexクラスに貼り付けてください。このコードは、従来のオブジェクトレベル及び項目レベルのアクセスチェックですでに保護されています。
  • 貼り付けたコードの13行目のSOQLクエリに WITH SECURITY_ENFORCED 句を追加してください。これにより手動の Schema.SObjectType チェックが冗長になります。
  • コードをリファクタリングして、冗長なオブジェクトと項目レベルのアクセスチェックを削除してください。
  • 権限が不十分な場合、他のタイプの例外ではなくSecurityExceptionでチェックされるようにして、既存の動作を維持してください。これには、WITH SECURITY_ENFORCED が throw する System.QueryException を catch して、new SecurityException を throw する必要があります。
  • オプション:これらの変更後の動作をテストしたい場合は、ワークベンチを利用してApex RESTサービスを呼び出すことができます。

Trailhead モジュール:インジェクションの脆弱性防止

※この内容は2019/4時点のものです。

アプリケーションセキュリティの使用開始

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_injection_vulnerabilities/secdev_inject_get_started_wappsec

  • 説明:日本語
  • Challenge:日本語選択問題

クロスサイトスクリプト (XSS) について

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_injection_vulnerabilities/secdev_inject_cross_site_scripting

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

このChallengeを完了するには、入力フィールドに有効なクロスサイトスクリプティング攻撃を実施する必要があります。

  • 「Cross-site Scripting (XSS)」アプリケーションの「XSS Basics Challenge」タブにアクセスしてください。
  • 入力フィールドを使用して、次の要件を満たすクロスサイトスクリプティングペイロードを入力してください。
    • <a> any text</a>」のように、HTMLテキストを含むもの
    • htmlタグ「<a>」の onmouseover プロパティを使用してJavaScriptアラートのポップアップを開始させるもの
  • 「Attempt XSS!」をクリックし、表示されたテキストにマウスカーソルを当て、ペイロードが成功していることを確認してください。

※筆者注:筆者が本ChallengeをChromeにて実施した際は、条件を満たすHTMLテキストを入力フィールドに入力し、「Attempt XSS!」をクリックしてもテキストは表示されませんでしたが、Challengeはクリアとなりました。

Lightning Platform に組み込まれている XSS 保護の確認

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_injection_vulnerabilities/secdev_inject_built_in_xss_protections

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「Cross-site Scripting (XSS)」アプリケーションの「Built-In XSS Protections Challenge」タブにアクセスし、「Visualforce Page」リンクをクリックしてください。
  • 「Built_In_XSS_Protections_Challenge」Visualforceページの、差し込み項目の右にあるコメントについて、以下の通り変更してください。
    • 脆弱性がある場合は「<!-- Line 10 is vulnerable to XSS: YES -- >」のようにしてください。
    • 脆弱性がない場合は「<!-- Line 10 is vulnerable to XSS: NO -- >」のようにしてください。

Lightning Platform アプリケーションでの XSS の防止

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_injection_vulnerabilities/secdev_inject_preventing_xss_inforce

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「Cross-site Scripting (XSS)」アプリケーションの「XSS Mitigations Challenge」タブにアクセスし、「Visualforce Page」リンクをクリックしてください。
  • 「XSS_Mitigations_Challenge」Visualforceページにある"{!sampleMergeField}"を探し、各フィールドに対し必要に応じてHTMLENCODE(), JSENCODE(), JSINHTMLENCODE()メソッドを使用してください。エンコーディングが不要なフィールドは変更しないでください。

SOQL インジェクションについて

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_injection_vulnerabilities/secdev_inject_soql_injection

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「SOQL Injection」アプリケーションの「SOQL Injection Challenge」タブにアクセスしてください。supply__cオブジェクトの検索ツールが表示されます。
  • 検索ボックスを使用して、貴族専用(Nobles only)の消耗品を返すSOQLインジェクションを実行してください。

ヒント:SOQLインジェクションに成功した場合、クエリは Venison を含む1レコードを結果として返すはずです。

コード内の SOQL インジェクションの防止

https://trailhead.salesforce.com/ja/content/learn/modules/secdev_injection_vulnerabilities/secdev_inject_prevent_soql_injection

  • 説明:日本語
  • Challenge:英語ハンズオン

【Challenge要約】

  • 「SOQL Injection」アプリケーションの「Prevent SOQL Injection Challenge」タブにアクセスしてください。複数の「Perform Search」ボタン付きの検索ボックスが表示されます。
  • 「Prevent_SOQL_Injection_Challenge」Apexコントローラには、動的クエリを含む3つのクエリ「stringSearchOne()」、「stringSearchTwo()」、「numberSearchOne()」があります。
  • 単一引用符のエスケープメソッドを使用して、「stringSearchOne()」、「stringSearchTwo()」の各クエリについてSOQLインジェクションを防止するよう修正してください。
  • 型キャストメソッドを使用して、「numberSearchOne()」各クエリについてSOQLインジェクションを防止するよう修正してください。

Kingdom Management DE組織で「アクセス権がありません」エラーが出た場合

※この内容は2019/4時点のものです。

事象

セキュアな Web アプリケーションの開発トレイルでは、Kingdom Management DE組織にサインアップして取得した組織を使用します。

Kingdom Management DE組織には、ユーザの権限が一部ない場合の動作を選択リストから選択することで確認できる画面があります。

f:id:mark-hammer:20190417002319p:plain
選択画面

さっそく、赤い部分を選択してみると…、

f:id:mark-hammer:20190417002404p:plain
「アクセス権がありません」エラー

「アクセス権がありません」というエラー画面が表示されます。

権限が関係する内容のため、この画面表示が正しいような気もしますが、Trailheadで示されている画面とは異なっています。

解消方法

この事象の原因は、ログインアクセスポリシーにある「管理者は任意のユーザでログインできます」設定がOFFになっていることが原因です。 先ほどの選択リスト画面で値を選択すると、該当ユーザへの代理ログイン処理を行うため、代理ログインの前提となる「管理者は任意のユーザでログインできます」がOFFの場合、エラーとなってしまうようです。

設定変更は、設定|セキュリティのコントロール|ログインアクセスポリシー の順にクリックし、「管理者は任意のユーザでログインできます」の有効化にチェックを入れて、「保存」をクリックすればOKです。

f:id:mark-hammer:20190417002532p:plain
設定画面

「管理者は任意のユーザでログインできます」の有効化にチェックを入れた後、同じように選択リストから選択すると…

f:id:mark-hammer:20190417002824p:plain
設定変更後に選択リストを選んだ画面

無事、Trailheadで示されている画面と同じものが表示されました。

参考URL

Trailhead Module: Identify CRUD and FLS Violations in Visualforce and Apex - Salesforce Developer Community