SOQL SOSL Injection
SOQL インジェクションの攻撃を回避するには、動的 SOQL クエリを使用しないようにします。代わりに、静的クエリとバインド変数を使用します。
動的 SOQL を使用する必要がある場合、escapeSingleQuotes メソッドを使用して、ユーザ指定の入力を削除します。
https://developer.salesforce.com/docs/atlas.ja-jp.pages.meta/pages/pages_security_tips_soql_injection.htm
例1.お勧め
{code}
String[] nameArray = new List{'test1'};
List nameList = new List{'test1'};
Map nameMap = new Map();
nameMap.put('test1', null);
List<Account> accountList = [
SELECT
Name
FROM Account
WHERE Name IN :nameMap.keySet()
or Name IN :nameArray
or name in :nameList
];
{/code}
例2.お勧め
{code}
List nameList = new List();
String appSqlCount = ' SELECT COUNT(Id) c FROM T_AttendanceApplication__c ';
appSqlCount += ' WHERE Id IN :nameList ';
LIST<AggregateResult> countList = Database.query(appSqlCount);
return (Integer)countList[0].get('c');
{/code}
例3.お勧めない
{code}
String str1 = (this.type == CONST)
? 'testA'
: ''' + String.escapeSingleQuotes(this.type) + ''';
String queryStr =
SQL_CONST_TEXT +
'field1__c = 'value1' and ' +
'field2__c in ' +
translateIdSet(new List(eids)) +
' and ' +
'from__c < ' +
this.to_date.format(DATETIME_FORMAT) +
' and ' +
'to__c >= ' +
this.from_date.format(DATETIME_FORMAT) +
' and ' +
'field3__c in (' +
str1 +
')' +
' and field4__c = false ' +
ORDER_TEXT;
List objList = Database.query(queryStr);
{/code}
** SELECT 処理はWITH SECURITY_ENFORCEDを付与する
** FLS Create (Field Level Security 項目レベルセキュリティ 数据库字段级权限安全)
- 単一レコード:
{code}
insert (【挿入対象】= (【挿入対象のクラスタイプ】) Security.stripInaccessible(AccessType.CREATABLE, new List{ 【挿入対象】}).getRecords().get(0));
{/code} - 複数レコード:
{code}
insert (【挿入対象リスト】= (【挿入対象のクラスタイプ】) Security.stripInaccessible(AccessType.CREATABLE, 【挿入対象リスト】).getRecords());
{/code} - エラー中断しない:
{code}
Database.insert(【挿入対象リスト】= (【挿入対象のクラスタイプ】) Security.stripInaccessible(AccessType.CREATABLE, 【挿入対象リスト】).getRecords(), false);
{/code} - ※対象作成や値設定する時、isCreateable()で権限チェックしないでも、「Force.com Code Scanner」をパスできる
** FLS Update
- 単一レコード:
{code}
update Security.stripInaccessible(AccessType.UPDATABLE, new List{ 【更新対象】}).getRecords();
{/code} - 複数レコード:
{code}
update Security.stripInaccessible(AccessType.UPDATABLE, 【更新対象リスト】).getRecords();
{/code} - エラー中断しない:
{code}
Database.update(Security.stripInaccessible(AccessType.UPDATABLE, 【更新対象リスト】).getRecords(), false);
{/code} - ※値設定する時、isUpdateable()で権限チェックしないでも、「Force.com Code Scanner」をパスできる
** CRUD Delete
- 検索正規表現式:([dD]{1}[eE]{1}[lL]{1}[eE]{1}[tT]{1}[eE]{1}[ (\n]+)
- 単一レコード:
{code}
if (【削除対象】.getSObjectType().getDescribe().isDeletable()) {
delete 【削除対象】;
}
{/code} - 複数レコード:
{code}
if (【削除対象リスト】[0].getSObjectType().getDescribe().isDeletable()) {
delete 【削除対象リスト】;
}
{/code}
** コート品質
| | Queries With No Where Or Limit Clause | 避免无条件和限制的查询 |
| | SOSL SOQL Statments Inside Loops | 在FOR循环中避免SOQL查询 |
| | Hardcoding Ids | 避免对ID进行硬编码 |
Apex Design Best Practices
https://developer.salesforce.com/ja/wiki/apex_code_best_practices
【Salesforce】 Apex代码的最佳实践
https://zhuanlan.zhihu.com/p/361439549
https://zhuanlan.zhihu.com/p/361723054