Não é possível arquivar_get_contents ou cURL via HTTPS

9

Eu tenho usado file_get_contents para pegar o conteúdo de um site por anos.

Recentemente, eles atualizaram seu URL para HTTPS e file_get_contents pararam de funcionar.

Li perguntas anteriores e tentei soluções marcadas, mas nada funcionou.

Por exemplo, tentei este e ele retornou o seguinte:

openssl: yes http wrapper: yes https wrapper: yes wrappers: array ( 0 => 'https', 1 => 'ftps', 2 => 'compress.zlib', 3 => 'compress.bzip2', 4 => 'php', 5 => 'file', 6 => 'data', 7 => 'http', 8 => 'ftp', 9 => 'zip', )

Então tentei esta solução com file_get_contents , sem sucesso.

Em seguida, tentei esta solução com cURL para ignorar completamente a criptografia, sem sucesso

Não importa qual solução eu tente, nada é retornado.

Eu não adicionei extension=php_openssl.dll e allow_url_include = On a PHP.ini conforme isso como este site específico está em um host compartilhado e a empresa de hospedagem não permite que o arquivo PHP.ini seja editado, embora eles já possam estar habilitados por padrão.

Eu tentei outros HTTPS sites e alguns funcionam e outros não, e não sei por quê.

Eu tentei de um servidor diferente (e IP diferente) no mesmo host, e também não funcionou com o destino HTTPS site.

Como posso depurar e corrigir isso?

ATUALIZAÇÃO:

phpinfo mostra:

curl cURL support enabled cURL Information libcurl/7.36.0 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5 libssh2/1.8.0

openssl OpenSSL support enabled OpenSSL Version OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008

    
por ProgrammerGirl 11.02.2017 в 11:58
fonte

6 respostas

2

RESPOSTA FINAL

Se o seu ISP não atualizar o openSSL para o TLS 1.2, você deve considerar seriamente outro ISP. Você deve testar seu servidor com o link "SSL SERVER TEST" abaixo. Seu servidor provavelmente tem vulnerabilidades de segurança SSL.

O servidor com o qual você está tentando se conectar suporta apenas o TLS 1.2 e o TLS 1.1
Não suporta: TLS 1.0, SSL 3, SSL2.

Quando uma solicitação SSL é feita, como parte do protocolo SSL, o curl apresenta uma lista de cifras para o servidor host. O servidor escolhe qual protocolo cifrado usar com base na lista apresentada por curl.

O host que você está tentando cont suporta estas cypher suites

TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)  
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)  
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x9f) 
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x9e)  
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)  
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)  
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x6b)  
TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x39) 
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027) 
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)  
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x67)  
TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x33) 
TLS_RSA_WITH_AES_256_GCM_SHA384 (0x9d) 
TLS_RSA_WITH_AES_128_GCM_SHA256 (0x9c) 
TLS_RSA_WITH_AES_256_CBC_SHA256 (0x3d) 
TLS_RSA_WITH_AES_256_CBC_SHA (0x35) 
TLS_RSA_WITH_AES_128_CBC_SHA256 (0x3c) 
TLS_RSA_WITH_AES_128_CBC_SHA (0x2f) 

Como o seu openSSL foi lançado em julho de 2008 e o TLSv1.2 foi lançado no mês seguinte, agosto de 2008, o melhor que você tem é o TLSv1.1

POSSÍVEL FIXAÇÃO TEMPORÁRIA até você atualizar

Eu não tenho um alto nível de confiança. Isso funcionará para você

Você deve testar o SSL do seu próprio servidor com algo como TESTE DE SERVIDOR SSL

Se o seu servidor suportar o TLS1.1, você poderá tentar o seguinte. Não posso testar isso porque não tenho a mesma versão do curl que você no servidor antigo com sua versão do openSSL.

Use a opção curl, CURLOPT_SSL_CIPHER_LIST, para impedir que o servidor host use outra coisa que não seja o TLS 1.1

curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1');
curl_setopt($ch, CURL_SSLVERSION_TLSv1_1);

Se não, tente:

curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'DEFAULT');
curl_setopt($ch, CURL_SSLVERSION_TLSv1_1);

LINHA DE FUNDO

Por mais razões do que este problema, você precisa atualizar seu openSSL.

-------------------------------------------------------------------------


 -

RESOLUÇÃO DE PROBLEMAS ANTERIORES ABAIXO DESTE PONTO

A primeira coisa que faço é desativar o javascript no navegador. Se eu puder recuperar a página com um navegador sem javascript, sei que posso obtê-lo com o PHP.

Eu construo a solicitação para ficar exatamente como no navegador. Eu vou para a aba Network do Inspector e edito o Request Header e copio e colo no meu código.

$request=array();$request[]='Host:example.com';$request[]='Connection:keep-alive';$request[]='Pragma:no-cache';$request[]='Cache-Control:no-cache';$request[]='Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';$request[]='User-Agent:Mozilla/5.0(WindowsNT5.1)AppleWebKit/537.36(KHTML,likeGecko)Chrome/41.0.2272.101Safari/537.36';$request[]='DNT:1';$request[]='Origin:https://example.com';$request[]='Referer:https://example.com/entry/login';$request[]='Accept-Encoding:gzip,deflate';$request[]='Accept-Language:en-US,en;q=0.8';

Iniciaronda

$url='https://example.com/entry/login';$ch=curl_init($url);

Adicioneosparâmetrosdasolicitação

curl_setopt($ch,CURLOPT_HTTPHEADER,$request);

Digaaocurlparaincluiroscabeçalhos

curl_setopt($ch,CURLOPT_VERBOSE,true);curl_setopt($ch,CURLINFO_HEADER_OUT,true);curl_setopt($ch,CURLOPT_HEADER,true);

Retornaaresposta

curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);

SigaosredirecionamentosRedirecionamentospodemserumaarmadilha.TalvezvocêNÃOtenhaqueacompanhareanalisararesposta.Muitasvezes,osredirecionamentosestãoláparadefinircookies.

curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true);curl_setopt($ch,CURLOPT_COOKIESESSION,true);

Deixeacompactaçãodoidentificadordecurvas

curl_setopt($ch,CURLOPT_ENCODING,"");

Defina os parâmetros de tempo limite

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_FAILONERROR,true);

Faça o pedido e obtenha resposta

O seguinte receberá tudo o que você precisa saber sobre as solicitações. O $ info também terá todos os cabeçalhos de redirecionamento. Se redirecionamentos forem feitos, o $ responseHeader terá todos os cabeçalhos de resposta.

UPDATE: novo código totalmente testado

Isso pode não importar, porque isso também funciona na minha máquina:

echo file_get_contents($url);

Se a curvatura falhar, esse código deve fornecer um motivo para que ela falhe.

Altere o URL. Este pertence a um cliente.

<?php
header('content-type: text/plain');

$url = 'https://amxemr.com';
$ch = curl_init($url);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING,"");
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_FAILONERROR,true);
curl_setopt($ch, CURLOPT_ENCODING,"");
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HEADER, true);


$data = curl_exec($ch);
if (curl_errno($ch)){
    echo 'Retreive Base Page Error: ' . curl_error($ch);
}
else {
  $info = rawurldecode(var_export(curl_getinfo($ch),true));

 // Get the cookies:

  $skip = intval(curl_getinfo($ch, CURLINFO_HEADER_SIZE)); 
  $responseHeader= substr($data,0,$skip);
  $data= substr($data,$skip);
  echo "HEADER: $responseHeader\n";
  echo "\n\nINFO: $info\n\nDATA: $data";
}  
?>

Se o acima não funcionou, execute phpinfo ()

<?php
phpinfo();
?>  

Deve haver uma seção de curvas e um openSSL.

--------------------------------------------------------------------

UPDATE TWO

Boas notícias

Eu sei o problema e consegui replicar os erros que você recebeu.

Retreive Base Page Error: 
Unknown SSL protocol error in connection to www.xxxx.com:443 

NOTA xxx foi o site do link que você me deu, você pode deletar essa mensagem agora.

Engraçado, eu tenho um servidor que não atualizo. E por sorte, tinha a mesma versão do openSSL de julho de 2008.

Você precisa atualizar seu openSSL. Também o file_get_contents () falhou neste servidor também. Ele trabalhou em uma versão de fevereiro de 2013 do openSSL, bem como em junho de 2014.

Eu não posso dizer se alguma coisa precisa ou não ser atualizada, assim como as funções que usam o openSSL podem (ou não) precisam ser atualizadas.

Eu vou com o ditado se não está quebrado, não conserte. Eu acredito que algumas atualizações são realmente baixas. Eu ainda estou no XP. Mas está quebrado e você precisa consertar isso.

Pelo menos não é um tiro no escuro. Estou confiante de que você precisa atualizar. Foi um procedimento de solução de problemas metódico que conseguiu duplicar seus erros. Você pode voltar a usar file_get_contents() também.

    
por Misunderstood 12.02.2017 / 09:18
fonte
1

use curl com curl para que você possa acessar facilmente qualquer página acima de https .

observe estas linhas:

curl_setopt($ch, CURLOPT_SSLVERSION, 4);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

aqui está o código de trabalho, testado para twitter e facebook

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
//ini_set('display_errors',1);
//$crawled = [];
set_time_limit(0);// to infinity for example
ob_start();
$output;
function grabAll($url){

$ch = curl_init();

// 2. set the options, including the url
curl_setopt($ch, CURLOPT_URL,$url);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// curl_setopt($ch, CURLOPT_HEADER, 0);


//curl_setopt ($ch, CURLOPT_CAINFO, "ca-cert/cacert.pem");

curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSLVERSION, 4);
//curl_setopt($ch, CURLOPT_HEADER, 1);
  curl_setopt($ch, CURLOPT_MAXREDIRS, '1L');

curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//curl_setopt($ch, CURLOPT_TIMEOUT, 400);   
//curl_setopt ($ch, CURLOPT_POST, 1);

// 3. execute and fetch the resulting HTML output
//curl_exec($ch);
$output = curl_exec($ch);
ob_flush();//Flush the data here
if ($output === FALSE) {

    echo "cURL Error: " . curl_error($ch);

}

$info = curl_getinfo($ch);



//echo 'Took ' . $info['total_time'] . ' seconds for url ' . $info['url'];


// 4. free up the curl handle
curl_close($ch);
//print_r($crawled);    


//return $output ;

echo $output;
}


grabAll('https://twitter.com/?lang=en');

UPDATE 1: use este código para salvar o arquivo

   function grab_image($url,$saveto){
        $ch = curl_init ($url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSLVERSION, 4);
        curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
        $raw=curl_exec($ch);
        curl_close ($ch);
        if(file_exists($saveto)){
            unlink($saveto);
        }
        $fp = fopen($saveto,'x');
        fwrite($fp, $raw);
        fclose($fp);
    }






  grab_image('i.imgur.com/85wsoLI.jpg','download/');

espero que isso tenha resolvido seu problema !!

aqui está uma demonstração no meu servidor: link

    
por EaBangalore 16.02.2017 / 06:01
fonte
0

se por nothing , você quer dizer um corpo de resposta vazio, não parece um problema httpS. se fosse, então curl_exec iria reclamar, curl_exec () retornaria bool (false) e curl_error () indicaria um problema SSL.

How can I debug and fix this?

investigue a solicitação enviada pelo seu navegador ao receber uma resposta válida (use as ferramentas de desenvolvedor do seu navegador para isso, por exemplo, a guia "Rede" no Ctrl + shift + i do Google Chrome) e compare-a com a solicitação enviada por curl quando você recebe uma resposta inválida (use CURLOPT_VERBOSE para isso) e 1 por 1, adicione todos os cabeçalhos que o navegador envia,

por exemplo, você notará que libcurl não envia nenhum user-agent header, enquanto seu navegador envia algo como user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 , então adicione esse cabeçalho. você também notará que a libcurl, por padrão, envia Accept: */* , enquanto o seu navegador envia Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 - para corrigir isso, faça o curl enviar os mesmos cabeçalhos.

continue fazendo isso, até que as duas solicitações sejam indistinguíveis e, ao longo do caminho, você encontrará a diferença que torna a curvatura bloqueada.

minha aposta está no cabeçalho do agente do usuário.

    
por hanshenrik 11.02.2017 / 13:07
fonte
0

Às vezes, ajuda a não validar o certificado e o host, mas simplesmente confia na criptografia em SSL.

$context = stream_context_create(
    array('http' => array(
            'follow_location' => true
        ),
        'ssl' => array(
            'verify_peer' => false, 
            'verify_peer_name' => false
        )
    )
);

$content = @file_get_contents($file, FALSE, $context);
    
por powtac 14.02.2017 / 18:37
fonte
0

O site HTTPS tem um certificado autoassinado? Você pode fornecer os nomes de domínio para alguns dos sites que funcionam e outros que não funcionam?

Você já tentou usar "allow_self_signed" => true na configuração do contexto de fluxo?

Então fica assim:

$arrContextOptions=array(
    "ssl"=>array(
        "verify_peer"=>false,
        "verify_peer_name"=>false,
        "allow_self_signed"=>true,
    ),
);  

$response = file_get_contents($url, false, stream_context_create($arrContextOptions));
    
por peiiion 16.02.2017 / 20:09
fonte
0

Como parece um problema com a versão SSL, você pode configurar o CURL para ignorá-lo usando CURLOPT_SSL_VERIFYPEER .

Aqui está um script trabalhando com o URL que você postou

$url = 'https://XXX/YYY/view-all';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
print_r($response);
    
por Iñaki Soria 18.02.2017 / 14:55
fonte