es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Problema de CSRF al importar un dashboard en Superset a través de la API de Node.js.

Me estoy enfrentando al error “flask_wtf.csrf: El token de sesión CSRF falta” al intentar importar un panel de control (con “VERSIONED_EXPORT” habilitado) a través de una llamada a la API POST de NodeJS. A continuación se muestra la misma configuración que funciona para todas mis otras llamadas a la API de Superset:

const config = {
  headers: {
    'X-CSRFToken': await this.getCsrfToken(),
    'Authorization': `Bearer ${await this.getAccessToken()}`
  }
}
axios.get<t>(url, config) //o
axios.post<t>(url, data, config)

Para la llamada a la API de importación del panel de control, estoy utilizando “form-data” y funciona si agrego la importación del panel de control a “WTF_CSRF_EXEMPT_LIST”, pero quiero evitar hacer eso, aunque no funciona con todos los enfoques que he intentado:

const formData = new FormData()
// Con X-CSRFToken (mostrado arriba)
formData.append('formData', fs.createReadStream(filePath))
// Con X-CSRFToken y nombre de archivo definido y longitud
var stat = fs.statSync(filePath);
formData.append('formData', fs.createReadStream(filePath), {filename: fileName, knownLength: stat.size})
// Con X-CSRFToken y/o Referral y/o Content-Type y/o Content-Length
var stat = fs.statSync(filePath);
formData.append('formData', fs.createReadStream(filePath), {filename: fileName, knownLength: stat.size})

const contentLength = formData.getLengthSync()
const config = {
  headers: {
    'X-CSRFToken': await this.getCsrfToken(),
    'Authorization': `Bearer ${await this.getAccessToken()}`,
    'Referrer': url,
    'Content-Type': 'multipart/form-data',
    'Content-Length': contentLength
  }
}

// Con X-XSRF-TOKEN
const config = {
  headers: {
    'X-XSRF-TOKEN': await this.getCsrfToken(),
    'Authorization': `Bearer ${await this.getAccessToken()}`
  }
}
formData.append('formData', fs.createReadStream(filePath))

await post(url, formData, config)

Sospecho que podría ser causado por “form-data”, que no puede manejar encabezados de token de CSRF, ya que puedo importar el panel de control en Postman:

Headers: {
  Authorization: 'Bearer {token}',
  X-CSRFToken: {csrfToken}
}
form-data: {
  formData: {uploadedFile}
}

Estoy abierto a sugerencias sobre cómo puedo importar el panel de control sin utilizar “form-data” en Node.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Posible solución para importar un panel sin utilizar form-data en node.js

    Puedes intentar usar multipart/form-data directamente con la cabecera Content-Type, en lugar de utilizar la biblioteca form-data. De esta manera, puedes añadir el token CSRF a las cabeceras y enviar el archivo en el cuerpo de la petición.

    A continuación se muestra un ejemplo de cómo puedes modificar tu código para lograr esto:

    const fs = require('fs');
    const axios = require('axios');
    
    const filePath = '/ruta/de/tu/archivo'; // Cambia esto por la ruta de tu archivo
    const fileName = 'dashboard.json'; // Cambia esto por el nombre de tu archivo
    
    
    const headers = {
      'X-CSRFToken': await this.getCsrfToken(),
      'Authorization': `Bearer ${await this.getAccessToken()}`,
      'Content-Type': 'multipart/form-data'
    };
    
    const data = new FormData();
    data.append('dashboard', fs.readFileSync(filePath), {filename: fileName});
    
    const config = {
      headers,
      maxContentLength: Infinity,
      maxBodyLength: Infinity,
      validateStatus: () => true
    };
    
    const url = '/superset/dashboard/import';
    
    try {
      const response = await axios.post(url, data, config);
      console.log(response.data);
    }
    catch (error) {
      console.error(error);
    }
    

    En el código anterior, estamos utilizando FormData() para crear una nueva instancia de multipart/form-data. Luego, añadimos el archivo a la instancia con el nombre correcto utilizando fs.readFileSync(). Por último, enviamos la petición con la configuración modificada.

    Ten en cuenta que también hemos añadido maxContentLength y maxBodyLength a la configuración para asegurarnos de que nuestra petición pueda manejar archivos grandes, y validateStatus para que siempre devuelva true para cualquier código de estado HTTP.

    Espero que esta solución te funcione. Avísame si tienes alguna pregunta o si encuentras algún problema al implementarla.

Comments are closed.