Http 406 error en javascript ajax post. Aceptar el conjunto de encabezado para aceptar todos

Recibo un error del servidor cuando bash realizar una solicitud AJAX que no puedo resolver. Es un error HTTP 406. Por lo que entiendo, esto significa que el servidor no puede enviar una respuesta en el formato que indica el encabezado Aceptar. Pero por lo que puedo ver, estoy Accept ing */* (comodín).

Puedes ver los detalles de mi solicitud HTTP en esta imagen. http://i.stack.imgur.com/fTfBf.png Mi solicitud HTTP

Este es mi código PHP para la página:

  
(snip - menu and header)
Saved!





Javascript:

 // Attach a submit handler to the form $( "#update-button" ).click( function( event ) { // Stop form from submitting normally event.preventDefault(); // Get some values from elements on the page: var $form = $('#template-form'); var template_id = $form.find( "input[name='id']" ).val(); var template_name = $form.find( "input[name='name']" ).val(); var template_value = $form.find( "textarea[name='value']" ).val(); var template_is_major = 'minor'; if( $( "input[name='major']" ).prop('checked') ){ template_is_major = "major"; } var url = $form.attr( "action" ); // Send the data using post var posting = $.post( url, { id: template_id, name: template_name, value: template_value, major: template_is_major, action: "Update Template" } ); // Show that the request has completed successfully posting.done(function( data ) { $('#notify-saved').slideDown(200).delay(500).slideUp(500); }); }); 

.

También es relevante el hecho de que este error solo ocurre parte del tiempo , por ejemplo, si el valor de plantilla enviado es

<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

entonces habrá un error, pero si se omite el encabezado < , entonces no hay ningún error:

script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

El php que recibe se ve así (post-actions.php):

  $v) { unset($process[$key][$k]); if (is_array($v)) { $process[$key][stripslashes($k)] = $v; $process[] = &$process[$key][stripslashes($k)]; } else { $process[$key][stripslashes($k)] = stripslashes($v); } } } unset($process); } require_once('database.php'); $dbo = new Database(); if( isset( $_REQUEST['action'] ) ){ switch( $_REQUEST['action'] ){ (snip - many irrelevant cases) case "Update Template": $dbo->UpdateTemplate( $_REQUEST[DB_TEMPLATES_ID], $_REQUEST[DB_TEMPLATES_NAME], $_REQUEST[DB_TEMPLATES_VALUE], $_REQUEST[DB_TEMPLATES_MAJOR] ); break; } } 

Y la clase de base de datos:

 db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME); if($this->db->connect_errno > 0){ die('Unable to connect to database [' . $this->db->connect_error . ']'); } $this->pdo = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8', DB_USER, DB_PASS ); $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); } function __destruct(){ $this->db->close(); $this->pdo = null; } $query = 'INSERT INTO `'.DB_TEMPLATES.'` ( `'.DB_TEMPLATES_NAME.'` ) VALUES ( :name )'; $stmt = $this->pdo->prepare($query); $stmt->bindValue(":name", $name, PDO::PARAM_INT); $stmt->execute(); } function updateTemplate($id, $name, $value, $major ){ if( $major == "major" ){ $major = 1; } else{ $major = 0; } $query = 'UPDATE `'.DB_TEMPLATES.'` SET `'.DB_TEMPLATES_NAME.'`=:name, `'.DB_TEMPLATES_VALUE.'`=:value, `'.DB_TEMPLATES_MAJOR.'`=:major WHERE `'.DB_TEMPLATES_ID.'`=:id'; $stmt = $this->pdo->prepare($query); $stmt->bindValue(":name", $name, PDO::PARAM_STR ); $stmt->bindValue(":value", $value, PDO::PARAM_STR ); $stmt->bindValue(":major", $major, PDO::PARAM_INT ); $stmt->bindValue(":id", $id, PDO::PARAM_INT ); $stmt->execute(); } $query = ' DELETE FROM '.DB_TEMPLATES.' WHERE '.DB_TEMPLATES_ID.'=:id'; $stmt = $this->pdo->prepare($query); $stmt->bindValue(":id", $id, PDO::PARAM_INT); $stmt->execute(); } (snip - irrelevant functions) } 

En ciertos puntos del camino, pensé que esto podría haber sido un problema de encoding de caracteres, pero ya no lo creo. Tal vez es un problema de escape de carácter extraño? Otras publicaciones aquí en SO parecen indicar que se trata de un problema de configuración / (¿característica?) De mod_security de apache. Intenté deshabilitar algunas cosas diferentes, pero eso no funcionó, y ahora no sé qué pensar.

Gracias por tu ayuda.

El hecho de tener un 406, y también el hecho de que esto se basa en la presencia del < antes de la palabra script , lleva directamente a un filtro de seguridad en acción. Por lo tanto, los archivos de configuración mod_security y apache serían más útiles que el código js / php para encontrar la regla de locking de raíz.

Esto parece un filtro anti-xss. Tal vez uno muy simple como:

 SecFilter "<( |\n)*script" 

Si puede modificar esta configuración mod_security, entonces haga eso ... o no. Se trata de la seguridad . Tal vez debería mantener este filtro en su lugar para proteger su aplicación para inyecciones de script realmente no deseadas. Tal vez la solución real sea que sus formularios de solicitud oficiales deben administrar las comunicaciones con el servidor sin sospechar de mod_security. Y aquí, su POST es demasiado parecido a un ataque de Cross Site Scripting para una herramienta que solo lee el flujo y detecta una llamada de JavaScript dentro.

Por ejemplo, podría agregar una encoding base64 en el valor POSTed (de js) y decodificar el resultado en el lado de PHP, algunas bibliotecas js de encoding base64 están disponibles en github.

De hecho, podría aplicar cualquier transformación en sus datos que los haga libres de HTML (y de Javascript), al menos para las herramientas de filtrado HTTP. Y Base64 suele ser la solución, pero verifique cómo la biblioteca utilizada administra la encoding de los caracteres utf-8, la verdadera base64 era solo ascii.

Tuve el mismo problema y te diré cómo lo depuré y lo arreglé.

En mi caso, podría reproducir la respuesta prohibida al escribir algunas directivas de CSS muy específicas (dentro de un atributo de estilo en una etiqueta html).

Analicé el archivo de registro de errores de apache (en mi caso, está en /usr/local/apache/logs/error_log y se filtra solo por el código de respuesta que estaba recibiendo.

 grep 406 error_log 

La explicación decía que era una regla de ModSecurity, esto es lo que decía:

 [Mon Jan 02 13:21:10.394376 2017] [:error] [pid 12827:tid 139784907347712] [client 255.255.255.255] ModSecurity: Access denied with code 406 (phase 2). Pattern match "(?: (?:height|width) ?(?:=|\\\\:) ?[0-9] ?px|overflow ?: ?(?:auto|hidden)|style ?= ?\\"? ?display ?: ?none ?)" at ARGS:body. [file "/usr/local/apache/conf/modsec2/30_asl_antispam.conf"] [line "174"] [id "300076"] [rev "29"] [msg "Atomicorp.com WAF AntiSpam Rules: Hidden Text Detected"] [data " height:8px"] [severity "CRITICAL"] [hostname "my.website.mx"] [uri "/index.php"] [unique_id "WGqoJqwQ25oAADIbgkcAAAGP"] 

Investigué cómo deshabilitar esto y resulta que puedes agregar esto en un archivo conf:

  SecRuleRemoveById 300076  

Problema resuelto para mí. Tenga en cuenta que si desea desactivar más de una regla, puede separar los identificadores por espacios.