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

Salesforce 链接到Apex方法的CSRF安全自定义按钮,salesforce,csrf,apex-code,visualforce,Salesforce,Csrf,Apex Code,Visualforce,我正在寻找一种技术,从添加到Opportunity对象的自定义按钮执行Apex代码,以保护用户免受CSRF的影响 当前使用的方法来自于问题-。基本上: 有一个Opportunity自定义按钮,其内容源设置为“Visualforce页面” 此按钮的内容设置为Visualforce页面,该页面使用standardController的Opportunity,并输入了扩展apex类和该类中方法的操作 action方法返回对另一个自定义Visualforce页面的PageReference,包括添加带有

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

当前使用的方法来自于问题-。基本上:

  • 有一个Opportunity自定义按钮,其内容源设置为“Visualforce页面”
  • 此按钮的内容设置为Visualforce页面,该页面使用standardController的Opportunity,并输入了扩展apex类和该类中方法的操作
  • action方法返回对另一个自定义Visualforce页面的PageReference,包括添加带有Opportunity Id的参数
  • 第二个自定义Visualforce页面完成了大部分实际工作,包括制作web服务调用和在将用户重定向回Opportunity之前执行DML操作
  • 这种方法的问题是,第二个自定义Visualforce页面通过HTTP GET检索,从查询字符串中提取参数,并在没有CSRF保护的情况下执行更新/插入DML操作。这是由Force.com安全源代码扫描程序获取的

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

    如何避免CSRF问题

    我不想在第二个visualforce页面中添加一个表单,该表单带有一个按钮,他们必须按下该按钮才能启动该过程(从而在回发中获得ViewStateCSRF保护)。从用户的角度来看,他们已经按下按钮来执行操作

    我以前在开发者力量论坛上问过这个问题,但没有找到解决方案-

    也许我应该尝试将代码移出第二个VisualForce页面的控制器,并改为使用stand控制器的扩展


    我可以切换到Apex Web服务的Javascript回调(如和中所建议的),但它似乎有点混乱,我不确定是否会打开Web服务的另一系列安全问题。

    为什么不首先使用Javascript按钮启动第二个页面?完全绕过第一页


    Salesforce将在呈现之前对脚本应用合并(因此您可以使用
    {!Opportunity.Id}
    在第二个URL中包含opp Id),您只需将浏览器重定向到第二个页面即可。

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

    如果需要CSRF保护(即发布到应用程序交换),则当前不支持我尝试执行的操作。他们提出了两种备选办法:

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

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


    嵌入式Visualforce页面必须使用标准对象控制器(在我的例子中是Opportunity)出现在标准页面布局上的可用Visualforce页面列表中。Visualforce页面本身可以非常小,只需
    中的一个commandButton,就可以查看他们是否可以通过自定义按钮直接添加对此的支持。

    我遇到的主要问题是,当用户通过HTTP GET请求到达第二个页面时,他们是向CSRF打开,因为第二个页面将接受查询字符串参数,并执行插入和更新操作以及Web服务调用。此外,使用Javascript,由于名称空间前缀的原因,我无法以在托管包内部和外部工作的方式引用目标visualforce页面。好的,#1您可以使用
    URLFOR
    >$Page.pagename
    或它们的组合来引用页面。这应该会解决您的命名空间问题。其次,CSRF应该只针对表单操作启动,我的理解是,您在第2页中没有这样的东西,不是吗?基本上是您的扩展构造函数完成了所有工作?如果是这样,您的页面将仍然对CSRF开放,无论发生什么,您都无法解决在salesforce呈现表单(带有令牌)并从
    加载提交表单时,您不需要使用此方法来解决CSRF问题(参见下一条注释)您无法解决此问题,因为知道您的页面的恶意网站仍然可以发送带有查询字符串的GET请求,并让salesforce为其创建一个令牌并为其提交。感谢您坚持此操作。关于使用Javascript,当我以前尝试在自定义按钮中使用带有$page.pagename的URLFOR时[我有一个错误]()。也许我应该重新考虑这个问题,因为它现在可以工作了?不幸的是,任何不依赖salesforce呈现表单并由用户发回表单的解决方案都对CSRF开放。您只会使安全漏洞更“奇特”,但您不会删除它。抱歉。
    
    <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);
        }
    }