【Apex Security and Sharing】在 Apex 中判断字段级别(FieldLevelSecurity)的权限(使用stripInaccessible方法)
2023年10月21日
文章浏览:330
需求:Apex的with sharing并不能对字段级别(FieldLevelSecurity)的权限生效(仍然是System Mode),需要取得字段的权限




现象:自定义开发的Lightning Web コンポーネント(LWC)输出各个字段,能够显示出自己没有权限的字段


LWC Html代码如下

<template>
    <lightning-card title='Custom Table' icon-name="custom:custom11">
        <table class="slds-table slds-table_cell-buffer slds-table_bordered">
            <thead>
                <tr class="slds-line-height_reset">
                  <th class="" scope="col">
                    <div class="slds-truncate" title="Account Name">Account Name</div>
                  </th>
                  <th class="" scope="col">
                    <div class="slds-truncate" title="Parent Account">Parent Account</div>
                  </th>
                  <th class="" scope="col">
                    <div class="slds-truncate" title="Type">Industry</div>
                  </th>
                  <th class="" scope="col">
                    <div class="slds-truncate" title="Rating">Rating</div>
                  </th>
                  <th class="" scope="col">
                    <div class="slds-truncate" title="Phone">Phone</div>
                  </th>
                  <th class="" scope="col">
                    <div class="slds-truncate" title="Ownership">Ownership</div>
                  </th>
                </tr>
              </thead>
              <tbody>
                <template for:each={records} for:item ='record'>
                <tr class="" key = {record.Id}>
                        <td data-label="Account Name">
                            <div class="slds-cell-wrap"><a href="javascript:void(0);">{record.Name}</a></div>
                        </td>
                        <td data-label="Parent Account">
                            <div class="slds-cell-wrap"><a href="javascript:void(0);">{record.ParentId}</a></div>
                        </td>
                        <td data-label="Industry">
                            <div class="slds-cell-wrap">{record.Industry}</div>
                        </td>
                        <td data-label="Rating">
                            <div class="slds-cell-wrap">{record.Rating}</div>
                        </td>
                        <td data-label="Phone">
                            <div class="slds-cell-wrap">{record.Phone}</div>
                        </td>
                        <td data-label="Ownership Name">
                            <div class="slds-cell-wrap">{record.Ownership}</div>
                        </td>
                </tr>
                </template>
            </tbody>
        </table>
    </lightning-card>
</template>


LWC JS代码如下

import { LightningElement,api,track,wire } from 'lwc';
import getAllAccounts from '@salesforce/apex/customTable.getAllAccounts';
export default class CustomTable extends LightningElement {
    @api records;
    @api errors;

    @wire(getAllAccounts,{
     }
    )
    wiredCases({
        data,error
    }){
    if(data){
        this.records = data;
        this.errors = undefined;
    }
    if(error){
        this.errors = error;
        this.records = undefined;
        }
    }
}


Apex代码如下

public with sharing class customTable {
    @AuraEnabled(cacheable = true)
    public static List<Account> getAllAccounts(){
        List<Account> accList =[Select Id,Name,Ownership,
                                Industry,Rating,ParentId,Phone FROM Account limit 10 ];
        return accList;
    }
}


用户的权限如下


displayAccountRecord.js-meta.xml的内容

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>55.0</apiVersion>
    <isExposed>true</isExposed>

    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__UtilityBar</target>
        <target>lightning__FlowScreen</target>
        <target>lightningCommunity__Page</target>
        <target>lightningCommunity__Default</target>
    </targets>

</LightningComponentBundle>



LWC执行效果如下(电话号码能够正常显示,这明显是不正确的效果,是错误





解决办法:使用stripInaccessible方法来去除所有没有权限的字段

LWC Html代码和JS代码都不需要改动


Apex代码如下

public with sharing class customTable {
    @AuraEnabled(cacheable = true)
    public static List<Account> getAllAccounts(){
        List<Account> accList =[Select Id,Name,Ownership,
                                Industry,Rating,ParentId,Phone FROM Account limit 10 ];

        system.debug('accList----处理前------>'+accList);
        SObjectAccessDecision securityDecision = Security.stripInaccessible(
            AccessType.CREATABLE,
            accList);
        system.debug('accList----处理后------>'+securityDecision.getRecords());

        return securityDecision.getRecords();
        //return accList;
    }
}



LWC执行效果如下(大家看到了,电话号码不再显示出来


再来看一下Debug Log的内容(我们可以看到,处理后的内容里面,已经没有电话号码了)

59.0 APEX_CODE,DEBUG;APEX_PROFILING,NONE;CALLOUT,NONE;DB,NONE;NBA,NONE;SYSTEM,NONE;VALIDATION,NONE;VISUALFORCE,NONE;WAVE,NONE;WORKFLOW,NONE
17:27:01.4 (4491402)|USER_INFO|[EXTERNAL]|0055h000007pzoS|yusizhong1234@gmail.com|(GMT+09:00) 日本標準時 (Asia/Tokyo)|GMT+09:00
17:27:01.4 (4602266)|EXECUTION_STARTED
17:27:01.4 (4627606)|CODE_UNIT_STARTED|[EXTERNAL]|apex://customTable/ACTION$getAllAccounts
17:27:01.4 (5524764)|CODE_UNIT_STARTED|[EXTERNAL]|01p5h00000SDeNW|customTable.getAllAccounts()
17:27:01.4 (13888465)|USER_DEBUG|[7]|DEBUG|accList----处理前------>(Account:{Id=0015h00001HDJIgAAP, Name=株式会社NextStep}, Account:{Id=0015h00000dzhxcAAA, Name=NextStepTraining}, Account:{Id=0015h000012S2KfAAK, Name=SalesforceGogogo, Industry=Agriculture, Phone=08088888888}, Account:{Id=0015h000012S2NUAA0, Name=MyPartner}, Account:{Id=0015h00001HEg5oAAD, Name=Gogogo, Phone=123456789}, Account:{Id=0015h00001FyJ8yAAF, Name=NameTest}, Account:{Id=0015h00000dzhxhAAA, Name=NextStepのCustomer}, Account:{Id=0015h00000ZDeKaAAL, Name=GenePoint, Ownership=Private, Industry=Biotechnology, Rating=Cold, Phone=(650) 867-3450}, Account:{Id=0015h00000ZDeKYAA1, Name=United Oil & Gas, UK, Ownership=Public, Industry=Energy, Phone=+44 191 4956203}, Account:{Id=0015h00000ZDeKZAA1, Name=United Oil & Gas, Singapore, Ownership=Public, Industry=Energy, Phone=(650) 450-8810})
17:27:01.4 (17000127)|USER_DEBUG|[11]|DEBUG|accList----处理后------>(Account:{Industry=null, ParentId=null, Ownership=null, Rating=null, Id=0015h00001HDJIgAAP, Name=株式会社NextStep}, Account:{Industry=null, ParentId=null, Ownership=null, Rating=null, Id=0015h00000dzhxcAAA, Name=NextStepTraining}, Account:{Industry=Agriculture, ParentId=null, Ownership=null, Rating=null, Id=0015h000012S2KfAAK, Name=SalesforceGogogo}, Account:{Industry=null, ParentId=null, Ownership=null, Rating=null, Id=0015h000012S2NUAA0, Name=MyPartner}, Account:{Industry=null, ParentId=null, Ownership=null, Rating=null, Id=0015h00001HEg5oAAD, Name=Gogogo}, Account:{Industry=null, ParentId=null, Ownership=null, Rating=null, Id=0015h00001FyJ8yAAF, Name=NameTest}, Account:{Industry=null, ParentId=null, Ownership=null, Rating=null, Id=0015h00000dzhxhAAA, Name=NextStepのCustomer}, Account:{Industry=Biotechnology, ParentId=null, Ownership=Private, Rating=Cold, Id=0015h00000ZDeKaAAL, Name=GenePoint}, Account:{Industry=Energy, ParentId=null, Ownership=Public, Rating=null, Id=0015h00000ZDeKYAA1, Name=United Oil & Gas, UK}, Account:{Industry=Energy, ParentId=null, Ownership=Public, Rating=null, Id=0015h00000ZDeKZAA1, Name=United Oil & Gas, Singapore})
17:27:01.4 (17166841)|CODE_UNIT_FINISHED|customTable.getAllAccounts()
17:27:01.4 (17660876)|CODE_UNIT_FINISHED|apex://customTable/ACTION$getAllAccounts
17:27:01.4 (17676981)|EXECUTION_FINISHED


参考文章

SObjectAccessDecision Class

https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_class_System_SObjectAccessDecision.htm 


stripInaccessible(accessCheckType, sourceRecords, enforceRootObjectCRUD)

ソースレコードから、現在のユーザの項目レベルセキュリティチェックに失敗した項目が除外された sObject のリストを作成します。このメソッドでは、オブジェクトレベルのアクセス権チェックを適用するオプションも提供されます。

 https://developer.salesforce.com/docs/atlas.ja-jp.244.0.apexcode.meta/apexcode/apex_class_System_Security.htm#apex_System_Security_stripInaccessible_2 

关注 收藏