2012-05-30 10 views
7

Estoy buscando una técnica para ejecutar el código Apex desde un botón personalizado agregado al objeto Opportunity de forma que proteja al usuario contra CSRF.CSRF seguro Botón personalizado vinculado al método Apex

El enfoque actual utilizado proviene de la pregunta - Custom Button or Link to a Visualforce page with a custom controller. Básicamente:

  1. Hay un botón personalizado de oportunidad con el origen del contenido establecido en "Página de Visualforce".
  2. El contenido de este botón se establece en una página Visualforce que utiliza Oportunidad para la standardController, tiene una clase ápice de extensión introducido y una acción por un método en el que la clase
  3. El método de acción devuelve un PageReference a otra página personalizada Visualforce , incluido agregar un parámetro con el ID de oportunidad.
  4. Esta segunda página personalizada de Visualforce realiza la mayor parte del trabajo real, incluida la realización de rótulos de servicios web y la realización de operaciones DML antes de redirigir al usuario a la oportunidad.

El problema con este enfoque es que la segunda página personalizada Visualforce se recupera a través de un HTTP GET, tira parámetros de la cadena de consulta, y realiza actualizar/insertar operaciones DML sin protección CSRF. Esto está siendo recogido por el escáner de código fuente de seguridad Force.com.

Debo añadir que este código apex se implementa como un paquete gestionado y no gestionado, de ahí el trabajo adicional para redirigir a la página de Visualforce objetivo utilizando una PageReference. Esto garantiza que se agregue el prefijo de espacio de nombres si es necesario.

¿Cómo puedo evitar el problema de CSRF?

No quiero agregar un formulario a la segunda página de Visualforce con un botón que deben presionar para iniciar el proceso (y por lo tanto, recuperar la protección ViewStateCSRF en la devolución de datos). Desde la perspectiva de los usuarios, ya han presionado el botón para realizar la operación.

que he hecho esta pregunta antes en el foro fuerza desarrollador y no llegar a una solución - Cross-Site Request Forgery (CSRF/XSRF) safe Custom Button action

Tal vez debería estar tratando de mover el código del controlador para la segunda página fuerza visual y el uso de la extensión para el controlador de stand en su lugar?

Podría cambiar a una devolución de llamada de Javascript a un servicio web de Apex (como se sugiere en Call a apex method from a custom button y How invoke APEX method from custom button), pero parece un poco complicado y no estoy seguro de si estaría abriendo otra gama de problemas de seguridad con el servicio web.

Respuesta

2

Reservé Horas de oficina de seguridad del socio con Salesforce y discutí este problema directamente con ellos.

Lo que estoy tratando de hacer no es compatible actualmente si se requiere protección CSRF (es decir, publicar en App Exchange).Sugirieron dos enfoques alternativos:

  1. Crear un formulario intermedio en una página de Visualforce que desencadena el Código Apex sensible. Por lo tanto, recogiendo la protección CSRF incorporada.
  2. Reemplazar la página Detalles de oportunidad (utilizando apex: Detalles para mostrar información similar). Esta nueva página de Visualforce incluiría una publicación de formulario similar en la opción 1 para invocar el código APEX sensible y obtener protección de CSRF automática.

Otro enfoque que no utiliza los botones personalizados es incrustar/en línea una página Visualforce (ver Embed a Page on a Standard Layout) que contiene sólo la tecla deseada en el diseño de página estándar.

La página incrustada Visualforce debe utilizar el controlador de objeto estándar (Oportunidad en mi caso) para aparecer en la lista de páginas de Visualforce disponibles en el diseño de página estándar. La página de Visualforce en sí misma puede ser muy mínima con solo un CommandButton dentro de un <apex:form>. La etiqueta de la página de Visualforce también puede ser se muestra en el diseño de página.

<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); 
    } 
} 

Esto debería proteger contra CSRF como el commandButton recogerá el "com.salesforce.visualforce.ViewStateCSRF" campo oculto con el puesto de vuelta al servidor dentro del marco flotante resultante.


He planteado la idea Invoking Apex code from the standard Entity Details pages with CSRF protection para ver si pueden añadir soporte para esto directamente con los botones personalizados.

0

¿Por qué no utiliza un botón de JavaScript en primer lugar para abrir la segunda página? Omitir la primera página por completo.

Salesforce aplicará la fusión al script antes de la representación (para que pueda usar {!Opportunity.Id} para incluir el ID de opp en el segundo URL) y simplemente puede redirigir el navegador a su segunda página.

+0

El principal problema que tengo es que cuando el usuario llega a la segunda página a través de una solicitud GET HTTP están abiertos a CSRF ya que la segunda página tomará el parámetro de cadena de consulta y realizará operaciones Insertar y Actualizar, así como llamadas al servicio web . Además, con Javascript no puedo hacer referencia a la página de Visualforce objetivo de tal manera que funcione tanto dentro como fuera de un paquete administrado debido al prefijo del espacio de nombres. –

+0

Ok, # 1 puedes usar 'URLFOR' o' $ Page.pagename' o su combinación para hacer referencia a la página. Esto debería resolver su problema de espacio de nombres. En segundo lugar, CSRF solo debe iniciar acciones de forma, tengo entendido que no tiene tal cosa en la página 2, ¿no? Esencialmente, su constructor de extensión hace todo el trabajo? Si es así, su página aún estará abierta a CSRF, sin importar qué, no puede resolver esto sin tener Salesforce renderizando el formulario (con token) y luego enviándolo desde 'onloaded'. Pero (y es un gran pero) no resuelve el CSRF con esto (ver el siguiente comentario) – mmix

+0

No lo resuelve porque el sitio malicioso con conocimiento de su página aún puede enviar una solicitud GET con cadena de consulta y tener el Salesforce crea un token para él y amablemente lo envía también. – mmix

Cuestiones relacionadas