我正在寻找一种从添加到Opportunity对象的自定义按钮执行Apex代码的技术,以保护用户免受CSRF侵害。

当前使用的方法来自问题Custom Button or Link to a Visualforce page with a custom controller。本质上:

  • 有一个机会自定义按钮,其内容源设置为“Visualforce页面”。
  • 此按钮的内容设置为Visualforce页面,该页面使用Opportunity作为standardController,输入了扩展顶点类,并且对该类中的方法进行了操作
  • action方法将PageReference返回到另一个自定义Visualforce页面,包括添加带有机会ID的参数。
  • 这是第二个自定义Visualforce页面,完成了大部分实际工作,包括进行Web服务标注和执行DML操作,然后将用户重定向回商机。

  • 这种方法的问题在于,第二个自定义Visualforce页面是通过HTTP GET检索的,从查询字符串中提取参数,并在没有CSRF保护的情况下执行更新/插入DML操作。 Force.com安全源代码扫描程序正在拾取此文件。

    我应该补充一点,此顶点代码既作为托管程序包也作为非托管程序包部署,因此需要使用PageReference重定向到目标Visualforce Page的额外工作。这样可以确保在需要时添加 namespace 前缀。

    如何避免CSRF问题?

    我不想使用一个按钮将表单添加到第二个visualforce页面,他们必须按下按钮才能启动该过程(因此需要在回发中获取ViewStateCSRF保护)。从用户的 Angular 来看,他们已经按下了按钮来执行操作。

    我之前在开发人员论坛上提出了这个问题,但没有提出解决方案-Cross-Site Request Forgery (CSRF/XSRF) safe Custom Button action

    也许我应该尝试将代码移出第二个视觉力页面的 Controller ,而改为使用支架 Controller 的扩展名?

    我可以切换到Apex Web Service的Javascript回调(如Call a apex method from a custom buttonHow invoke APEX method from custom button中的建议),但似乎有些困惑,我不确定是否要通过Web Service打开另一系列的安全性问题。 。

    最佳答案

    我与Salesforce预订了合作伙伴安全办公时间,并直接与他们讨论了这个问题。

    如果需要CSRF保护(即发布到App Exchange),当前不支持我尝试执行的操作。他们提出了两种替代方法:

  • 在Visualforce页面中创建一个触发敏感Apex代码的中间表单。因此,选择内置的CSRF保护。
  • 覆盖商机详细信息页面(使用apex:Details显示类似信息)。这个新的Visualforce页面将包含一个类似的表格,该表格回传到选项1,以调用敏感的APEX代码并获得自动CSRF保护。


  • 另一种不使用自定义按钮的方法是在Visualforce页面中嵌入/嵌入(请参阅Embed a Page on a Standard Layout),其中仅在标准页面布局中包含所需的按钮)。

    嵌入式Visualforce页面必须使用标准对象 Controller (在本例中为“机会”)才能出现在标准页面布局上的可用Visualforce页面列表中。仅在<apex:form>内使用一个commandButton,Visualforce页面本身可以非常小。 Visualforce页面的标签也可以显示在页面布局中。
    <apex:page id="embeddedPage" StandardController="Opportunity" extensions="OpportunityExtensionController" showHeader="false" standardStylesheets="true">
    <apex:form >
        <apex:commandButton value="CSRF Safe Button" action="someMethodInTheExtensionClass" />
    </apex:form>
    
    public with sharing class OpportunityExtensionController {
    
        private final Opportunity opportunityFromController;
    
        public OpportunityExtensionController(ApexPages.StandardController controller) {
            opportunityFromController = (Opportunity)controller.getRecord();
        }
    
        public PageReference someMethodInTheExtensionClass() {
    
            // Perform directly here within the postback rather than redirecting to another page to prevent against XSRF
    
            System.debug('opportunityFromController.Id:' + opportunityFromController.Id);
        }
    }
    

    这应该可以防止CSRF,因为commandButton会拾取隐藏的“com.salesforce.visualforce.ViewStateCSRF”输入,并将帖子发回到结果iframe中的服务器。

    我提出了Idea Invoking Apex code from the standard Entity Details pages with CSRF protection,以查看他们是否可以使用自定义按钮直接添加对此的支持。

    07-24 18:21