我正在寻找一种技术,以保护用户免受CSRF的方式,从添加到Opportunity对象的自定义按钮执行Apex代码。
目前使用的方法来自问题 - Custom Button or Link to a Visualforce page with a custom controller。基本上:
此方法的问题是第二个自定义Visualforce页面是通过HTTP GET检索的,从查询字符串中提取参数,并执行更新/插入DML操作而没有CSRF保护。这是由Force.com安全源代码扫描程序提取的。
我应该补充一点,这个顶点代码被部署为托管和非托管包,因此使用PageReference重定向到目标Visualforce页面的额外工作。这可确保在需要时添加名称空间前缀。
如何避免CSRF问题?
我不想在第二个visualforce页面上添加一个表单,只需按一下按钮即可启动该进程(从而在回发中获取ViewStateCSRF保护)。从用户角度来看,他们已按下按钮执行操作。
我之前在开发者力量论坛上问过这个问题并没有提出解决方案 - Cross-Site Request Forgery (CSRF/XSRF) safe Custom Button action
也许我应该尝试将代码移出第二个视觉强制页面的控制器并使用扩展到控制台控制器?
我可以切换到Apex Web服务的Javascript回调(如Call a apex method from a custom button和How invoke APEX method from custom button中所示),但它看起来有点乱,我不确定我是否只是通过Web服务解决另一系列安全问题。
答案 0 :(得分:2)
我使用Salesforce预订了合作伙伴安全办公时间,并直接与他们讨论了此问题。
如果需要CSRF保护(即发布到App Exchange),目前我不支持我要做的事情。他们提出了两种替代方法:
另一种不使用自定义按钮的方法是嵌入/内联Visualforce页面(请参阅标准页面布局中仅包含所需按钮的Embed a Page on a Standard Layout)。
嵌入式Visualforce页面必须使用标准对象控制器(在我的情况下为Opportunity)才能显示在标准页面布局上的可用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内的服务器。
我已经提出了想法Invoking Apex code from the standard Entity Details pages with CSRF protection,看看他们是否可以使用自定义按钮直接添加对此的支持。
答案 1 :(得分:0)
为什么不首先使用JavaScript按钮来启动第二页?完全绕过第一页。
Salesforce将在渲染之前将合并应用于脚本(因此您可以使用{!Opportunity.Id}
在第二个URL中包含opp id),您只需将浏览器重定向到第二页即可。