CSRF安全自定义按钮链接到Apex方法

Dan*_*ger 7 salesforce csrf visualforce apex-code

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

当前使用的方法来自问题 - 自定义按钮或链接到带有自定义控制器的Visualforce页面.实质上:

  1. 有一个机会自定义按钮,内容源设置为"Visualforce页面".
  2. 此按钮的内容设置为Visualforce页面,该页面使用Opportunity for standardController,输入了扩展名apex类,并为该类中的方法执行操作
  3. action方法将PageReference返回到另一个自定义Visualforce页面,包括添加带有Opportunity Id的参数.
  4. 第二个自定义Visualforce页面执行大部分实际工作,包括制作Web服务标注和执行DML操作,然后再将用户重定向到Opportunity.

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

我应该补充一点,这个顶点代码被部署为托管和非托管包,因此使用PageReference重定向到目标Visualforce页面的额外工作.这可确保在需要时添加名称空间前缀.

如何避免CSRF问题?

我不想在第二个visualforce页面上添加一个表单,只需按一下按钮即可启动该进程(从而在回发中获取ViewStateCSRF保护).从用户的角度来看,他们已经按下按钮来执行操作.

我之前在开发人员论坛上问过这个问题并没有提出解决方案 - 跨站点请求伪造(CSRF/XSRF)安全自定义按钮操作

也许我应该尝试将代码从控制器中移出第二个可视化力页并使用扩展到支架控制器?

我可以切换到Apex Web服务的Javascript回调(如从自定义按钮调用apex方法如何从自定义按钮调用APEX方法中的建议),但它看起来有点乱,我不确定我是不是只是打开Web服务的另一系列安全问题.

Dan*_*ger 3

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

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

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

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

嵌入式 Visualforce 页面必须使用标准对象控制器(在我的例子中为 Opportunity)才能显示在标准页面布局上的可用 Visualforce 页面列表中。Visualforce 页面本身可以非常小,只需在<apex:form>. 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>
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该可以防止 CSRF,因为 commandButton 将拾取“com.salesforce.visualforce.ViewStateCSRF”隐藏输入,并在生成的 iframe 内发回服务器。


从具有 CSRF 保护的标准实体详细信息页面中提出了调用 Apex 代码的想法,看看他们是否可以使用自定义按钮直接添加对此的支持。