2013-08-15 8 views
24

Vorrei verificare sul lato server se una richiesta alla mia pagina php è una richiesta Ajax o meno.Come verificare se la richiesta è una richiesta AJAX con PHP

Ho visto due modi per farlo:

Primo modo: l'invio di un parametro GET nella richiesta che racconta la pagina che si tratta di una richiesta AJAX (= mypage.php?ajax)

mypage.php:

if(isset($_GET['ajax'])) { 
    //this is an ajax request, process data here. 
} 

secondo modo: impostare un'intestazione ai xmlHttpRequest:

js lato client:

xmlHttpRequestObject.open(“GET”,url,true); 
xmlHttpRequestObject.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 

mypage.php:

if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { 
    //request is ajax 
} 

Il fatto è che, questi due modi di farlo può essere facilmente violato, quindi non è sicuro di controllare se ottengo una richiesta AJAX come questo .

Come posso verificare se sto ricevendo una richiesta AJAX?

+5

Basta tenere a mente: "MAI fidarsi del lato client". Non puoi sapere da dove viene fatta una richiesta. Potresti spoofare/camuffare/fingere (quasi) tutto. – DaGardner

+0

Possibile duplicato di http://stackoverflow.com/questions/4301150/how-do-i-check-if-the-request-is-made-via-ajax-with-php – JRizz

+0

@ ChristianGärtner Lo so, ecco perché ho postato la domanda Non penso che esista un modo sicuro al 100% per farlo, ma penso che ci debba essere un modo per rendere complicato per gli "hacker" falsificare la richiesta (magari gestendola lato server) – BackSlash

risposta

20

Non esiste un modo sicuro per sapere che è stata effettuata una richiesta tramite Ajax. Non puoi mai fidarti dei dati provenienti dal client. Potresti usare un paio di metodi diversi, ma possono essere facilmente superati con lo spoofing.

+1

Sì. Sono abbastanza sicuro che non esiste un modo sicuro al 100% per farlo. Ma penso che ci debba essere un modo per rendere complicato per gli "hacker" falsificare la richiesta (magari gestendola lato server?) – BackSlash

+3

@BackSlash Potresti renderlo complicato, ma sarebbe la sicurezza attraverso l'oscurità. Personalmente, non ci farei affidamento. La tua migliore scommessa sarebbe probabilmente un token che cambia per richiesta. O un captcha. –

+0

Stavo pensando ai cookie, vengono inviati con una richiesta Ajax? – BackSlash

-3

Si può provare a utilizzare una variabile $_SESSION per assicurarsi che sia stata effettuata una richiesta da un browser. In caso contrario, è possibile inviare la richiesta tramite un database o un file [lato server].

+1

come si può definire' $ _SESSION' dal client? – nmnsud

6

impostare una variabile di sessione per ogni pagina del tuo sito (pagine reali non comprende o RPC) che contiene il nome della pagina corrente, quindi nella chiamata ajax passare un nonce salata con il $ _SERVER [ 'SCRIPT_NAME']:

<?php 
function create_nonce($optional_salt='') 
{ 
    return hash_hmac('sha256', session_id().$optional_salt, date("YmdG").'someSalt'.$_SERVER['REMOTE_ADDR']); 
} 
$_SESSION['current_page'] = $_SERVER['SCRIPT_NAME']; 
?> 

<form> 
    <input name="formNonce" id="formNonce" type="hidden" value="<?=create_nonce($_SERVER['SCRIPT_NAME']);?>"> 
    <label class="form-group"> 
    Login<br /> 
    <input name="userName" id="userName" type="text" /> 
    </label> 
    <label class="form-group"> 
    Password<br /> 
    <input name="userPassword" id="userPassword" type="password" /> 
    </label> 
    <button type="button" class="btnLogin">Sign in</button> 
</form> 
<script type="text/javascript"> 
    $("form.login button").on("click", function() { 
     authorize($("#userName").val(),$("#userPassword").val(),$("#formNonce").val()); 
    }); 

    function authorize (authUser, authPassword, authNonce) { 
     $.ajax({ 
      type: "POST", 
      url: "/inc/rpc.php", 
      dataType: "json", 
      data: "userID="+authUser+"&password="+authPassword+"&nonce="+authNonce 
     }) 
     .success(function(msg) { 
      //some successful stuff 
     }); 
    } 
</script> 

poi nella RPC si chiamano test nonce è stato superato, se è buona, allora le probabilità sono abbastanza grandi che il vostro RPC è stato legittimamente chiamato:

<?php 
function check_nonce($nonce, $optional_salt='') 
{ 
    $lasthour = date("G")-1<0 ? date('Ymd').'23' : date("YmdG")-1; 
    if (hash_hmac('sha256', session_id().$optional_salt, date("YmdG").'someSalt'.$_SERVER['REMOTE_ADDR']) == $nonce || 
     hash_hmac('sha256', session_id().$optional_salt, $lasthour.'someSalt'.$_SERVER['REMOTE_ADDR']) == $nonce) 
    { 
     return true; 
    } else { 
     return false; 
    } 
} 

$ret = array(); 
header('Content-Type: application/json'); 
if (check_nonce($_POST['nonce'], $_SESSION['current_page'])) 
{ 
    $ret['nonce_check'] = 'passed'; 
} else { 
    $ret['nonce_check'] = 'failed'; 
} 
echo json_encode($ret); 
exit; 
?> 

edit: FYI il modo in cui ho impostato il nonce è buono solo per un'ora e cambia, quindi se non hanno aggiornato il pa ge effettuando la chiamata ajax nell'ultima ora o 2 la richiesta ajax fallirà.

29

Ecco il tutorial del raggiungimento del risultato.

Esempio:

if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') 
{  
    exit;  
} 
continue; 

Questo controlla se il parametro HTTP_X_REQUESTED_WITH non è vuota e se è uguale a xmlhttprequest, allora sarà uscire dal copione.

+0

AFAIK '$ _SERVER ['HTTP_X_REQUESTED_WITH']' può essere contraffatto, quindi non è che non saprai per certo che si tratta di una richiesta AJAX. Comunque questa è una pessima risposta, controlla [Come rispondere] (http://stackoverflow.com/questions/how-to-answer): *** Fornisci il contesto per i link *** - * Un link a una potenziale soluzione è sempre il benvenuto, ma per favore aggiungi un contesto intorno al link in modo che i tuoi colleghi possano avere un'idea di cosa sia e perché sia ​​lì. * *** Citare sempre la parte più rilevante di un link importante, nel caso il sito target sia irraggiungibile o diventa permanente offline. *** – BackSlash

+2

Questa risposta è ESTREMAMENTE pertinente ora perché l'app Android di Facebook invia con 'HTTP_X_REQUESTED_WITH = com.facebook.katana. Aggiungendo nell'ultimo controllo' == 'xmlhttprequest'' È necessario implementare questo controllo di digita con il nuovo browser di Facebook, altrimenti potrebbero succedere cose strane. – Tschallacka

3
$headers = apache_request_headers(); 
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest'); 
+1

Alcune intestazioni possono essere facilmente falsificate. 'X-Requested-With' è uno di questi, poiché è impostato dal client. Ecco perché non voglio usarlo. – BackSlash

+0

Sì, non è sicuro, ma se devi semplicemente decidere il formato della risposta, puoi usarlo. – revoke

+0

Questo NON funziona con l'app Android per Android, imposta x-request-with su com.facebook.katana! – Blackfire

1

Questa funzione sta usando nel quadro Yii per il check-Ajax chiamata.

public function isAjax() { 
     return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest'; 
} 
+0

non in yii questo codice funziona su tutti i framework –