各種程式語言忽略http的SSL證書認證

janbar發表於2020-11-16

前言

我們內部測試的http伺服器很多時候證照都是沒有經過第三方認證的,我們傳送http請求基本上都是忽略證照認證。
我總結了一下常用程式語言使用http請求時忽略證照認證的程式碼片段,記錄一下下。

程式碼

go語言

func httpPost(url, body string) ([]byte, error) {
    req, err := http.NewRequest(http.MethodPost, urlPre+url, strings.NewReader(body))
    if err != nil {
        return nil, err
    }
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
 
    client := &http.Client{ // 忽略證照驗證
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                InsecureSkipVerify: true,
            },
        },
    }
    resp, err := client.Do(req)
    if resp != nil {
        defer resp.Body.Close()
    }
    if err != nil {
        return nil, err
    }
 
    data, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    return data, nil
}

Python語言

import json
import requests

try:
    # verify = False 表示忽略證照
    response = requests.post("http://www.baidu.com/",verify = False, headers = header, data = "")
    data = json.loads(response.text)
    print(data)
except Exception as e:
    print('error:', e)

Ruby語言

require 'rest-client'
require 'json'
 
begin
    # :verify_ssl => OpenSSL::SSL::VERIFY_NONE 表示忽略證照
    resp = RestClient::Request.execute(method: :post, url: "http://www.baidu.com/", payload: "", headers: headers, :verify_ssl => OpenSSL::SSL::VERIFY_NONE)
    data = JSON.parse(resp.body)
    puts(data)
rescue => e
    puts("#{e.class}, #{e.message}")
end

Java語言

package iotp;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.cert.X509Certificate;
 
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
 
public class janbar {
    public static void main(String[] args) {
        trustAllHosts(); // 只在開頭執行一次即可
 
        String data = httpPost("http://www.baidu.com/", "");
        System.out.println(data);
    }
 
    public static String httpPost(String httpUrl, String param) {
        HttpsURLConnection connection = null;
        InputStream is = null;
        OutputStream os = null;
        BufferedReader br = null;
        String result = null;
        try {
            // 通過遠端url連線物件開啟連線
            connection = (HttpsURLConnection) new URL(urlPre + httpUrl).openConnection();
            // 忽略證照認證
            connection.setHostnameVerifier(DO_NOT_VERIFY);
            // 設定連線請求方式
            connection.setRequestMethod("POST");
            // 設定連線主機伺服器超時時間:15000毫秒
            connection.setConnectTimeout(15000);
            // 設定讀取主機伺服器返回資料超時時間:60000毫秒
            connection.setReadTimeout(60000);
 
            // 預設值為:false,當向遠端伺服器傳送資料/寫資料時,需要設定為true
            connection.setDoOutput(true);
            // 預設值為:true,當前向遠端服務讀取資料時,設定為true,該引數可有可無
            connection.setDoInput(true);
            // 設定傳入引數的格式:請求引數應該是 name1=value1&name2=value2 的形式。
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            // 通過連線物件獲取一個輸出流
            os = connection.getOutputStream();
            // 通過輸出流物件將引數寫出去/傳輸出去,它是通過位元組陣列寫出的
            os.write(param.getBytes());
            // 通過連線物件獲取一個輸入流,向遠端讀取
            if (connection.getResponseCode() == 200) {
                is = connection.getInputStream();
                // 對輸入流物件進行包裝:charset根據工作專案組的要求來設定
                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
 
                StringBuffer sbf = new StringBuffer();
                String temp = null;
                // 迴圈遍歷一行一行讀取資料
                while ((temp = br.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append("\r\n");
                }
                result = sbf.toString();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 關閉資源
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 斷開與遠端地址url的連線
            connection.disconnect();
        }
        return result;
    }
 
    private static void trustAllHosts() {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[] {};
            }
 
            public void checkClientTrusted(X509Certificate[] chain, String authType) {
            }
 
            public void checkServerTrusted(X509Certificate[] chain, String authType) {
            }
        } };
        // Install the all-trusting trust manager
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    private final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };
}

PHP語言

<?php
function httpPost($url, $content) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳過證照檢查
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 從證照中檢查SSL加密演算法是否存在
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type','application/x-www-form-urlencoded'));
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
    $response = curl_exec($ch);
    if($error=curl_error($ch)){
        die($error);
    }
    curl_close($ch);
    return $response;
}
$data = httpPost("http://www.baidu.com/", "");
$data = json_decode($data, true);
var_dump($data);

C#語言

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
 
namespace SundrayApi
{
    class Program
    {
        static void Main(string[] args)
        {
            string data = apiPost("http://www.baidu.com/", "");
            Console.WriteLine(data);
 
            Console.ReadLine();
        }
 
        static string apiPost(string url, string body)
        {
            string content = string.Empty;
            try
            {
                /* 跳過ssl驗證 */
                ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
                HttpWebRequest request = HttpWebRequest.Create(preUrl + url) as HttpWebRequest;
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                byte[] data = Encoding.UTF8.GetBytes(body);
                Stream newStream = request.GetRequestStream();
                newStream.Write(data, 0, data.Length);
                newStream.Close();
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream stream = response.GetResponseStream();
                StreamReader reader = new StreamReader(stream, Encoding.UTF8);
                content = reader.ReadToEnd();
                reader.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                content = ex.ToString();
            }
            return content;
        }
    }
}

C/C++語言

c語言需要編譯一下下,如下流程即可。
wget https://curl.haxx.se/download/curl-7.73.0.tar.gz
./configure
make
gcc test.c -l curl -L /root/c/curl/curl-7.73.0/lib/.libs -I /root/c/curl/curl-7.73.0/include

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
 
typedef struct {
  char *memory;
  size_t size;
} MemoryStruct;
 
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
  size_t realsize = size * nmemb;
  MemoryStruct *mem = (MemoryStruct *)userp;
 
  char *ptr = realloc(mem->memory, mem->size + realsize + 1);
  if(ptr == NULL) { /* out of memory! */
    printf("not enough memory (realloc returned NULL)\n");
    return 0;
  }
  mem->memory = ptr;
  memcpy(&(mem->memory[mem->size]), contents, realsize);
  mem->size += realsize;
  mem->memory[mem->size] = 0;
  return realsize;
}
 
int httpPost(const char *url, char *data, int size)
{
    int ret = -1;
    if(url == NULL || data == NULL){
        return ret;
    }
 
    CURL *curl = curl_easy_init();
    struct curl_slist* headers;
    long   retcode = 0;
 
    MemoryStruct chunk;
    chunk.size   = 0;
    chunk.memory = malloc(1);
 
    headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
 
    curl_easy_setopt(curl, CURLOPT_POST, 1);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
 
    CURLcode res = curl_easy_perform(curl);
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &retcode);
    if (res == CURLE_OK && retcode == 200) {
        ret = 0;
        if (chunk.size > 0) {
            if (chunk.size > size)
                chunk.size = size - 1; /* 超出限制,不拷貝 */
            memcpy(data, chunk.memory, chunk.size);
        }
        data[chunk.size] = 0; /* 結束符 */
    } else {
        ret = -2;
    }
 
    curl_easy_cleanup(curl);
    free(chunk.memory);
    return ret;
}
  
int main(int argc, char *argv[])
{
    int url_len = 128, data_len = 2048;
    char *url  = (char *)malloc(sizeof(char) * url_len);
    char *data = (char *)malloc(sizeof(char) * data_len);
 
    strcpy(url,  "http://www.baidu.com/");
    strcpy(data, "");
    int ret = httpPost(url, data, data_len);
    if (ret != 0) {
        return ret;
    }
    printf("[%s]\n\n",data);
    return 0;
}

shell語言

#!/bin/bash

# 使用 -k 引數忽略證照
data=$(curl -s -k "http://www.baidu.com/" -d "")
echo "$data"

總結

把常用程式語言的http忽略證照程式碼做個筆記,方便以後再來檢視。本來想謝謝lua的,但是lua連socket都得編譯個庫來搞,還是以後有需求再搞搞吧。
另外再附上https跳過證照校驗底層原理

相關文章