Jump to content

POWERED BY:

gustavopinent

Erro cURL unable to get local issuer certificate

Recommended Posts

Olá! Esse erro ocorre em um php simples rodando em um servidor compartilhado Locaweb: SSL certificate problem: unable to get local issuer certificate. O php faz uma requisição ao site do Cep Aberto para consulta de endereço informando o CEP (https://www.cepaberto.com/api/v3/cep?cep=95020520)

 

Olhei o php.ini e não tem nenhuma menção ao arquivo de certificados. Então peguei alguns tutoriais, baixei o arquivo "cacert.pem", coloquei lá e defini o curl no próprio php, ficou assim:

			$ch = curl_init($url);
			curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Token token="' . $token . '"']);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
			curl_setopt($ch, CURLOPT_CAINFO, $cacert);
			curl_setopt($ch, CURLOPT_CAPATH, $cacert);
			$res = curl_exec($ch);
			if($res===FALSE) {
				$Res["erro"] = "curl";
				$Res["msg"] = "Execução CURL falhou!";
				$Res["descr"] = curl_error($ch);
			} else {
				$Res["dados"] = json_decode($res);
				$Res["http"] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
				$Res["erro"] = ($Res["http"]==200)? "OK" : "http" ;
				$Res["msg"] = ($Res["http"]==200)? "" : "Erro HTTP ".$Res["http"] ;
			}

Onde $cacert é o endereço do arquivo "cacert.pem", verificado antes por is_file. Mas o erro é o mesmo, como se eu nada tivesse feito. Tem que configura o Apache? Não sei como configurar o Apache, será que posso? Desabilitar o SSL do php é uma opção que não tentei ainda, dizem que não é aconselhável...

 

O PHP é o 5.6 (pretendo ir pro 7.4 em breve) e o servidor é CENTOS 5.11 compartilhado, hospedagem Locaweb.

 

Alguma ideia? 

Share this post


Link to post
Share on other sites

Como você não passou a $url, eu usei $url="facebook.com", assim

 

<?php
$url="facebook.com";
$ch = curl_init($url);
//curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Token token="' . $token . '"']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//curl_setopt($ch, CURLOPT_CAINFO, $cacert);
//curl_setopt($ch, CURLOPT_CAPATH, $cacert);
$res = curl_exec($ch);
if($res===FALSE) {
				$res["erro"] = "curl";
				$res["msg"] = "Execução CURL falhou!";
				$res["descr"] = curl_error($ch);
			} else {
                var_dump($res);
				//$res["dados"] = json_decode($res);
				//$res["http"] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
				//$res["erro"] = ($res["http"]==200)? "OK" : "http" ;
				//$res["msg"] = ($res["http"]==200)? "" : "Erro HTTP ".$res["http"] ;
            }

mas não consegui a mesma mensagem de erro que você.

Share this post


Link to post
Share on other sites

Eu consegui o token e mesmo assim não consegui fazer o cURL funcionar. Eu sinto muito.

Mesmo assim, eu achei no Google outra forma de consultar o CEP:

<meta charset="utf-8">
<h1>Pesquisar Endereço</h1>
<form action="" method="post">
  <input type="text" name="cep">
  <button type="submit">Pesquisar Endereço</button>
</form>
<?php
function get_endereco($cep){
  // formatar o cep removendo caracteres nao numericos
  $cep = preg_replace("/[^0-9]/", "", $cep);
  $url = "http://viacep.com.br/ws/$cep/xml/";
  $xml = simplexml_load_file($url);
  return $xml;}
if($_POST['cep']){
	echo "<h2>Resultado da Pesquisa</h2><p>";
	$endereco = get_endereco($_POST['cep']);
	echo "<table>";
  	echo "<tr><td>CEP:<td>$endereco->cep";
  	echo "<tr><td>Logradouro:<td>$endereco->logradouro";
  	echo "<tr><td>Bairro:<td>$endereco->bairro";
  	echo "<tr><td>Localidade:<td>$endereco->localidade";
  	echo "<tr><td>UF:<td>$endereco->uf</table>"; }

 

Share this post


Link to post
Share on other sites

Oi boa noite! Tudo bem?

 

No caso qual o valor da variável $cacert ? Me mostra o caminho do certificado pois o ideal é usar o caminho absoluto tipo /var/www/html/certificados/arquivo.pem

...

curl_setopt($ch, CURLOPT_CAINFO, $cacert);
curl_setopt($ch, CURLOPT_CAPATH, $cacert);

...

 

Esse certificado que você está usando você baixou de um site aleatório ou é desta empresa da $url?

 

Se você quiser pode testar desativando a verificação do certificado (ssl) se não você precisa de um certificado válido no seu servidor para usar o que é o recomendado.

$ch = curl_init($url);
			curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Token token="' . $token . '"']);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			//curl_setopt($ch, CURLOPT_CAINFO, $cacert);
			//curl_setopt($ch, CURLOPT_CAPATH, $cacert);
			$res = curl_exec($ch);
			if($res===FALSE) {
				$Res["erro"] = "curl";
				$Res["msg"] = "Execução CURL falhou!";
				$Res["descr"] = curl_error($ch);
			} else {
				$Res["dados"] = json_decode($res);
				$Res["http"] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
				$Res["erro"] = ($Res["http"]==200)? "OK" : "http" ;
				$Res["msg"] = ($Res["http"]==200)? "" : "Erro HTTP ".$Res["http"] ;
			}

 

 

Share this post


Link to post
Share on other sites
1 hora atrás, André Severino disse:

Oi boa noite! Tudo bem?

 

No caso qual o valor da variável $cacert ? Me mostra o caminho do certificado pois o ideal é usar o caminho absoluto tipo /var/www/html/certificados/arquivo.pem


...

curl_setopt($ch, CURLOPT_CAINFO, $cacert);
curl_setopt($ch, CURLOPT_CAPATH, $cacert);

...

 

Esse certificado que você está usando você baixou de um site aleatório ou é desta empresa da $url?

 

Se você quiser pode testar desativando a verificação do certificado (ssl) se não você precisa de um certificado válido no seu servidor para usar o que é o recomendado.


$ch = curl_init($url);
			curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Token token="' . $token . '"']);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			//curl_setopt($ch, CURLOPT_CAINFO, $cacert);
			//curl_setopt($ch, CURLOPT_CAPATH, $cacert);
			$res = curl_exec($ch);
			if($res===FALSE) {
				$Res["erro"] = "curl";
				$Res["msg"] = "Execução CURL falhou!";
				$Res["descr"] = curl_error($ch);
			} else {
				$Res["dados"] = json_decode($res);
				$Res["http"] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
				$Res["erro"] = ($Res["http"]==200)? "OK" : "http" ;
				$Res["msg"] = ($Res["http"]==200)? "" : "Erro HTTP ".$Res["http"] ;
			}

 

 

Eu testei o código do André Veríssimo e deu certo. Aqui o código teste que eu fiz:

 

<?php
$url="https://www.cepaberto.com/api/v3/cep?cep=95020520";
$token="c4f34d1210626b65990f1b764a822552";
$ch = curl_init($url);
			curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Token token="' . $token . '"']);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			//curl_setopt($ch, CURLOPT_CAINFO, $cacert);
			//curl_setopt($ch, CURLOPT_CAPATH, $cacert);
			$res = curl_exec($ch);
			$jes= json_decode($res,true);  // testando a resposta
			var_dump($jes); // testando a resposta
			exit; // testando a resposta
			if($res===FALSE) {
				$Res["erro"] = "curl";
				$Res["msg"] = "Execução CURL falhou!";
				$Res["descr"] = curl_error($ch);
			} else {
				$Res["dados"] = json_decode($res);
				$Res["http"] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
				$Res["erro"] = ($Res["http"]==200)? "OK" : "http" ;
				$Res["msg"] = ($Res["http"]==200)? "" : "Erro HTTP ".$Res["http"]
			}

e aqui a resposta:

 

C:\wamp64\www\astudy\astudy.php:13:
array (size=9)
  'altitude' => float 817
  'cep' => string '95020520' (length=8)
  'latitude' => string '-29.1707900004' (length=14)
  'longitude' => string '-51.1821951652' (length=14)
  'logradouro' => string 'Rua Sinimbu' (length=11)
  'bairro' => string 'São Pelegrino' (length=14)
  'complemento' => string '- de 2151 ao fim - lado ímpar' (length=30)
  'cidade' => 
    array (size=3)
      'ddd' => int 54
      'ibge' => string '4305108' (length=7)
      'nome' => string 'Caxias do Sul' (length=13)
  'estado' => 
    array (size=1)
      'sigla' => string 'RS' (length=2)

 

Share this post


Link to post
Share on other sites

Sim, o que eu fiz foi desativar o SSL através das linhas citadas porque achei um preciosismo de segurança.

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

O ViaCEP também é uma opção, acho que estava fora do ar na época e eu acabei usando o CEP Aberto.

Porém, me preocupa o fato do CURL insistir em não carregar o arquivo. Podemos precisar em um projeto no futuro. Vou postar todo o código aqui, até como contribuição, não há tutorial em PHP no site CEP Aberto. O código permite fazer vários tipos de consulta a partir de um JavaScript e obter o retorno em JSON, mas também permite testes direto no navegador.

<?php
header('HTTP/1.1 200 OK');
header('Content-Type: text/plain; charset=utf-8');
define("ROOT", dirname(__FILE__)."/");
$api = (isset($_GET["api"]))? $_GET["api"] : FALSE ; // método: cep, nearest, address e cities
$req = (isset($_GET["req"]))? $_GET["req"] : FALSE ; // dados em json
$token = 'meusegredinho'; // token do CEP Aberto
$cacert = ROOT.'cacert.pem'; // Certificados SSL
//
$Res = ["erro"=>"OK", "msg"=>"", "dados"=>[], "url"=>"", "http"=>0, "descr"=>""];
//
if(is_file($cacert)) {
	if($api && $req) {
		$query = http_build_query(json_decode($req, TRUE));
		$url = 'https://www.cepaberto.com/api/v3/'.$api.'?'.$query;
		$Res["url"] = $url;
		try {
			$ch = curl_init($url);
			curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Token token="' . $token . '"']);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			//curl_setopt($ch, CURLOPT_CAINFO, $cacert);
			//curl_setopt($ch, CURLOPT_CAPATH, $cacert);
			$res = curl_exec($ch);
			if($res===FALSE) {
				$Res["erro"] = "curl";
				$Res["msg"] = "Execução CURL falhou!";
				$Res["descr"] = curl_error($ch);
			} else {
				$Res["dados"] = json_decode($res);
				$Res["http"] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
				$Res["erro"] = ($Res["http"]==200)? "OK" : "http" ;
				$Res["msg"] = ($Res["http"]==200)? "" : "Erro HTTP ".$Res["http"] ;
			}
			curl_close($ch);
		} catch(Exception $e) {
			$Res["erro"] = "?";
			$Res["msg"] = "Erro desconhecido";
			$Res["descr"] = $e;
		}
	} else {
		$Res["erro"] = "params";
		$Res["msg"] .= (!$api)? "Parâmetro api não informado " :  "" ;
		$Res["msg"] .= (!$req)? "Parâmetro req não informado " : "" ;
	}
} else {
	$Res["erro"] = "cacert";
	$Res["msg"] =  "Arquivo de certificados SSL não encontrado.";
	$Res["descr"] = "Arquivo requerido não encontrado em '".$cacert."'.";
}
switch($_GET["teste"]){
	case "txt":
		echo("url: ".$url."\nerro: ".$Res["erro"]."\nmsg: ".$Res["msg"]."\nhttp: ".$Res["http"]."\ndados: \n".json_encode($Res["dados"], JSON_PRETTY_PRINT)."\ndescr: \n".json_encode($Res["descr"], JSON_PRETTY_PRINT));
		break;
	case "json":
	default:
		echo(json_encode($Res));
}
?>
<?php
header('HTTP/1.1 200 OK');
header('Content-Type: text/plain; charset=utf-8');
define("ROOT", dirname(__FILE__)."/");
$api = (isset($_GET["api"]))? $_GET["api"] : FALSE ; // método: cep, nearest, address e cities
$req = (isset($_GET["req"]))? $_GET["req"] : FALSE ; // dados em json
$token = 'c546794c1f405bf6e1b74aba4147cff1'; // token do CEP Aberto
$cacert = ROOT.'cacert.pem'; // Certificados SSL
//
$Res = ["erro"=>"OK", "msg"=>"", "dados"=>[], "url"=>"", "http"=>0, "descr"=>""];
//
if(is_file($cacert)) {
	if($api && $req) {
		$query = http_build_query(json_decode($req, TRUE));
		$url = 'https://www.cepaberto.com/api/v3/'.$api.'?'.$query;
		$Res["url"] = $url;
		try {
			$ch = curl_init($url);
			curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Token token="' . $token . '"']);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			//curl_setopt($ch, CURLOPT_CAINFO, $cacert);
			//curl_setopt($ch, CURLOPT_CAPATH, $cacert);
			$res = curl_exec($ch);
			if($res===FALSE) {
				$Res["erro"] = "curl";
				$Res["msg"] = "Execução CURL falhou!";
				$Res["descr"] = curl_error($ch);
			} else {
				$Res["dados"] = json_decode($res);
				$Res["http"] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
				$Res["erro"] = ($Res["http"]==200)? "OK" : "http" ;
				$Res["msg"] = ($Res["http"]==200)? "" : "Erro HTTP ".$Res["http"] ;
			}
			curl_close($ch);
		} catch(Exception $e) {
			$Res["erro"] = "?";
			$Res["msg"] = "Erro desconhecido";
			$Res["descr"] = $e;
		}
	} else {
		$Res["erro"] = "params";
		$Res["msg"] .= (!$api)? "Parâmetro api não informado " :  "" ;
		$Res["msg"] .= (!$req)? "Parâmetro req não informado " : "" ;
	}
} else {
	$Res["erro"] = "cacert";
	$Res["msg"] =  "Arquivo de certificados SSL não encontrado.";
	$Res["descr"] = "Arquivo requerido não encontrado em '".$cacert."'.";
}
switch($_GET["teste"]){
	case "txt":
		echo("url: ".$url."\nerro: ".$Res["erro"]."\nmsg: ".$Res["msg"]."\nhttp: ".$Res["http"]."\ndados: \n".json_encode($Res["dados"], JSON_PRETTY_PRINT)."\ndescr: \n".json_encode($Res["descr"], JSON_PRETTY_PRINT));
		break;
	case "json":
	default:
		echo(json_encode($Res));
}
?>

 

Share this post


Link to post
Share on other sites

Oi que bom que conseguiu :grin:

 

Em 10/09/2022 at 15:37, gustavopinent disse:

Sim, o que eu fiz foi desativar o SSL através das linhas citadas porque achei um preciosismo de segurança.

O SSL está em nossa vida para melhorar a segurança de nossos sistemas e ajudar os usuários, não é um preciosismo, o ideal é usar várias camadas de segurança e usar um certificado válido faz parte de uma delas.

 

Em 10/09/2022 at 15:37, gustavopinent disse:

...

Porém, me preocupa o fato do CURL insistir em não carregar o arquivo. Podemos precisar em um projeto no futuro. ...

Se você passou o caminho do arquivo corretamente, ele está carregando sim. O problema é que você está usando um certificado inválido então ele não roda xD mas se você precisar usar no futuro basta usar um certificado válido e passar o caminho corretamente no curl.

 

Abraço e qualquer dúvida só postar xD

Share this post


Link to post
Share on other sites
2 horas atrás, André Severino disse:

Oi que bom que conseguiu :grin:

 

Se você passou o caminho do arquivo corretamente, ele está carregando sim. O problema é que você está usando um certificado inválido então ele não roda xD mas se você precisar usar no futuro basta usar um certificado válido e passar o caminho corretamente no curl.

 

Abraço e qualquer dúvida só postar xD

Ocorre que o erro retornado pelo curl é o mesmo após feita a alteração, e remete ao arquivo local, não ao certificado do CEP Aberto. Mas vou manter isso em mente, especialmente quando a requisição for mais "séria". Eu achava que o php estava encontrando o arquivo mas não conseguia processá-lo de fato. Então é culpa do CEP Aberto? Na minha humilde opinião, eles não deveriam deixar assim, não ajuda a tornar a Internet mais segura.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By violin101
      Caros amigos, saudações.
       
      Por favor, me permita tirar uma dúvida com os amigos.

      Tenho um Formulário onde o Usuário digita todos os Dados necessários.

      Minha dúvida:
      --> como faço após o usuário digitar os dados e salvar, o Sistema chamar uma Modal ou mensagem perguntando se deseja imprimir agora ?

      Grato,
       
      Cesar
    • By Carcleo
      Tenho uma abela de usuarios e uma tabela de administradores e clientes.
      Gostaria de uma ajuda para implementar um cadastro
       
      users -> name, login, passord (pronta) admins -> user_id, registratiom, etc.. client -> user_id, registratiom, etc...
      Queria ajuda para extender de user as classes Admin e Client
      Olhem como estáAdmin
      <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Admin extends User {     use HasFactory;            protected $fillable = [         'name',         'email',         'password',         'registration'     ];      private string $registration;     public function create(         string $name,          string $email,          string $password,         string $registration     )     {         //parent::create(['name'=>$name, 'email'=>$email, 'password'=>$password]);         parent::$name = $name;         parent::$email = $email;         parent::$password = $password;         $this->registration = $registration;     } } User
      <?php namespace App\Models; // use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class User extends Authenticatable {     /** @use HasFactory<\Database\Factories\UserFactory> */     use HasFactory, Notifiable;     static string $name;     static string $email;     static string $password;     /**      * The attributes that are mass assignable.      *      * @var list<string>      */     protected $fillable = [         'name',         'email',         'password',     ];          /**      * The attributes that should be hidden for serialization.      *      * @var list<string>      */     protected $hidden = [         'remember_token',     ];     /**      * Get the attributes that should be cast.      *      * @return array<string, string>      */     protected function casts(): array     {         return [             'email_verified_at' => 'datetime',             'password' => 'hashed',         ];     }          public function roles() : BelongsToMany {         return $this->belongsToMany(Role::class);     }       public function hasHole(Array $roleName): bool     {                 foreach ($this->roles as $role) {             if ($role->name === $roleName) {                 return true;             }         }         return false;     }         public function hasHoles(Array $rolesName): bool     {                 foreach ($this->roles as $role) {             foreach ($rolesName as $rolee) {             if ($role->name === $rolee) {                 return true;             }          }         }         return false;     }         public function hasAbility(string $ability): bool     {         foreach ($this->roles as $role) {             if ($role->abilities->contains('name', $ability)) {                 return true;             }         }         return false;     }     } Como gravar um Admin na tabela admins sendo que ele é um User por extensão?
      Tentei assim mas é claro que está errado...
      public function store(Request $request, Admin $adminModel) {         $dados = $request->validate([             "name" => "required",             "email" => "required|email",             "password" => "required",             "registration" => "required"         ]);         $dados["password"] =  Hash::make($dados["password"]);                  $admin = Admin::where("registration",  $dados["registration"])->first();                  if ($admin)              return                    redirect()->route("admin.new")                             ->withErrors([                                 'fail' => 'Administrador já cadastrados<br>, favor verificar!'                   ]);                            $newAdmin = $adminModel->create(                                    $dados['name'],                                    $dados['email'],                                    $dados['password'],                                    $dados['registration']                                 );         dd($newAdmin);         $adminModel->save();         //$adminModel::create($admin);                  return redirect()->route("admin.new")->with("success",'Cadastrado com sucesso');     }  
    • By violin101
      Caros amigos, saudações.
       
      Gostaria de tirar uma dúvida com os amigos, referente a PDV.
       
      Estou escrevendo um Sistema com Ponto de Vendas, a minha dúvida é o seguinte, referente ao procedimento mais correto.

      Conforme o caixa vai efetuando a venda, o Sistema de PDV já realiza:
      a baixa direto dos produtos no estoque
      ou
      somente após concretizar a venda o sistema baixa os produtos do estoque ?
       
      Grato,
       
      Cesar
       
    • By violin101
      Caros amigos do grupo, saudações e um feliz 2025.
       
      Estou com uma pequena dúvida referente a Teclas de Atalho.

      Quando o Caps Lock está ativado o Comando da Tecla de Atalho não funciona.
      ou seja:
      se estiver para letra minúscula ====> funciona
      se estiver para letra maiúscula ====> não funciona
       
      Como consigo evitar essa falha, tanto para Letra Maiúscula quanto Minúscula ?

      o Código está assim:
      document.addEventListener( 'keydown', evt => { if (!evt.ctrlKey || evt.key !== 'r' ) return;// Não é Ctrl+r, portanto interrompemos o script evt.preventDefault(); });  
      Grato,
       
      Cesar
    • By violin101
      Caros amigos, saudações.
       
      Por favor, poderiam me ajudar.

      Estou com a seguinte dúvida:
      --> como faço para para implementar o input código do produto, para quando o usuário digitar o ID o sistema espera de 1s a 2s, sem ter que pressionar a tecla ENTER.

      exemplo:
      código   ----   descrição
           1       -----   produto_A
       
      Grato,
       
      Cesar
×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.