我從我的 C 代碼發送這個請求:
char * request = "GET / HTTP/1.1\r\n" \
"Host: www.some.com\r\n" \
"Connection: keep-alive\r\n" \
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36\r\n" \
"Accept: text/html,application/xhtml xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nAccept-Language: en-US,en;q=0.9\r\nAccept-Encoding: gzip, deflate\r\n\r\n";
但是在發送上述請求后我得到了這個回應:
HTTP/1.1 302 Found
Location: https://www.some.com/?gws_rd=ssl
Cache-Control: private
Content-Type: text/html; charset=UTF-8
BFCache-Opt-In: unload
Date: Thu, 24 Feb 2022 06:17:10 GMT
Server: gws
Content-Length: 231
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Set-Cookie: 1P_JAR=2022-02-24-06; expires=Sat, 26-Mar-2022 06:17:10 GMT; path=/; domain=.some.com; Secure; SameSite=none
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="https://www.some.com/?gws_rd=ssl">here</A>.
</BODY></HTML>
這是訊息<A HREF="https://www.some.com/?gws_rd=ssl">here</A>.,所以如果我關注https://www.some.com/?gws_rd=ssl我沒有收到任何資料,它的類似請求正在發送但沒有收到資料。我將此請求發送到https://www.some.com/?gws_rd=ssl
char *x="GET / https://www.some.com/?gws_rd=ssl\r\n\r\n";
這是為什么。我的 http/https 有什么問題。
我正在使用 openSSL。
因此,在發送初始請求后,服務器將資源移動到新的 url。現在,當我關注新網址時,什么也沒有發生,沒有資料回應
代碼:
/* filename nossl.c */
#include "stdio.h"
#include "string.h"
#include "openssl/ssl.h"
#include "openssl/bio.h"
#include "openssl/err.h"
int main()
{
BIO * bio;
char resp[1024];
int ret;
//char * request = "GET /cas/login?service=https://web.corp.ema-tech.com:8888/ HTTP/1.1\x0D\x0AHost: web.corp.ema-tech.com\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A";
char * request = "GET / HTTP/1.1\r\n" \
"Host: www.yoursite.com\r\n" \
"Connection: keep-alive\r\n" \
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36\r\n" \
"Accept: text/html,application/xhtml xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nAccept-Language: en-US,en;q=0.9\r\nAccept-Encoding: gzip, deflate\r\n\r\n";
char *x="GET / https://www.yoursite.com/?gws_rd=ssl\r\n\r\n";
/* Set up the library */
ERR_load_BIO_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
/* Create and setup the connection */
//bio = BIO_new_connect("web.corp.ema-tech.com:8888");
printf("___________________________ \n");
bio = BIO_new_connect("www.yoursite.com:80");
if(bio == NULL) {
printf("====___________________________-\n");
printf("BIO is null\n");
}
if(BIO_do_connect(bio) <= 0) {
printf(" ___________________________@\n");
BIO_free_all(bio);
}
printf("___________________________@^\n");
/* Send the request */
BIO_write(bio, request, strlen(request));
printf("___________________________0\n");
/* Read in the response */
for(;;) {
ret = BIO_read(bio, resp, 1023);
printf("----%d\n",ret);
if(ret <= 0) break;
resp[ret] = 0;
printf("%s\n", resp);
}
BIO_write(bio,x,sizeof("GET / https://www.yoursite.com/?gws_rd=ssl\r\n\r\n"));
for(;;) {
ret = BIO_read(bio, resp, 1023);
printf("----%d\n",ret);
if(ret <= 0) break;
resp[ret] = 0;
printf("%s\n", resp);
}
/* Close the connection and free the context */
BIO_free_all(bio);
return 0;
}
uj5u.com熱心網友回復:
如果您的第一個請求是 HTTP(不是 HTTPS),那么服務器主要是告訴您使用 HTTPS 而不是 HTTP。你的要求是
char * request = "GET /?gws_rd=ssl HTTP/1.1\r\n" \
"Host: www.some.com\r\n" ...
/?gws_rd=ssl 是本地資源名稱 (/) 和來自https://www.some.com/?gws_rd=ssl的查詢字串 (?gws_rd=ssl) ,而主機名www.some.com去到“主機:”標題。某些服務器僅在您使用服務器名稱 TLS 擴展(OpenSSL:“SSL_set_tlsext_host_name”)并提供主機名時才允許連接。
您還可以考慮將 C 現有庫用于 HTTPS 客戶端,例如:
- libcurl ( https://curl.se/libcurl/ - libcurl 是 C 語言中最常用的 HTTP/HTTPS 客戶端庫之一)
- CivetWeb(https://github.com/civetweb/civetweb/blob/master/docs/api/mg_connect_client_secure.md - 實際上是一個帶有一些額外客戶端功能的服務器;免責宣告:我在這個服務器的維護團隊中)。
兩者都是開源和 MIT 許可的。
編輯:
其實我需要知道openssl和https之間的區別
HTTPS 是一種通信協議(安全超文本傳輸??協議)。OpenSSL 是一個加密庫。
HTTP 的協議堆疊如下:
HTTP: [HTTP]
[TCP/IP]
來自 HTTPS 的堆疊如下所示:
HTTPS: [HTTP]
[TLS (= SSL)]
[TCP/IP]
SSL 代表 Secure Sockets Layer,而 TLS(Transport Layer Security)是 SSL 的繼承者。OpenSSL 實作 SSL 版本 2 和 3(均已棄用)以及所有版本的 TLS(1.0、1.1、1.2 和 1.3)。OpenSSL 可以提供 HTTPS 堆疊的中間部分,但您仍然需要頂部和底部部分。它們與 HTTP 相同,因此在中間插入了 TLS(協議)和 OpenSSL(實作協議的庫)。
要查看此實際操作,請嘗試使用 OpenSSL 命令列從www.google.com讀取:
$ openssl s_client www.google.com
服務器將提供一些資訊,特別是服務器證書。然后你輸入:
GET / HTTP/1.1
Host: www.google.com
Connection: close
在底部的空行之后,服務器將發送一個標頭:
HTTP/1.1 200 OK
Date: ..
Server: gws
Connection: close
后面是一個空行,最后是一個 HTML 頁面。
This OpenSSL command line client will implement the TLS layer and use the TCP/IP layer from the operating system. But you have to provide the HTTP layer on top: The four lines of text (GET ..., Host ..., Connection ... and the empty line at the end) is a valid HTTP protocol request.
The full source of s_client can be found here: https://github.com/openssl/openssl/blob/master/apps/s_client.c The source is lengthy because it provides a hundred different options.
A much smaller client example with more explanation can be found here: https://wiki.openssl.org/index.php/SSL/TLS_Client You will find the same four lines for the HTTP protocol in this example:
BIO_puts(web, "GET " HOST_RESOURCE " HTTP/1.1\r\n"
"Host: " HOST_NAME "\r\n"
"Connection: close\r\n\r\n");
In your code you used "Connection: keep-alive". That's perfectly fine if you want to make multiple HTTP requests using the same HTTP connection. Just make sure the last request you want to make used "Connection: close". Also be aware that a HTTP server may decide to close the connection at any time by sending a "Connection: close" header. "Connection: close" is easier to begin with.
If you only want to download a web page, these four lines of code are usually enough - unless you need a login/cookies/access token/... for a specific web site. Additional requests such as POST (e.g, submitting a web form) will require more lines on top of OpenSSL. If you need this, you should consider using an additional library instead of implementing it on your own.
The response of the server needs to be split into header (everything above the first empty line) and body (everything below). Depending on the header, it might be required to interpret the body data differently. For example, www.google.com will send one header line "Transfer-Encoding: chunked" (instead of "Content-Length: ####"). This are two different ways a server can let the client know how long the body data is supposed to be. If you get a "Content-Length: 1234" header, you know that you have to read 1234 bytes in your HTTP protocol implementation. If you get a "Transfer-Encoding: chunked" header, the server will first send a hex number, followed by "\r\n". Followed by as many bytes as the hex number stated before. Followed by another hex number, "\r\n" and more data. Finally a hex number "0" will indicate the end of the data. The hex numbers and "\r\n" are not part of the HTML page - you need to remove it (if you keep it, you will end up with broken HTML or whatever you want to download). If a server neither sends "Content-Length:" nor "Transfer-Encoding:" then you need to read until the server closes the connection. This is also part of the HTTP protocol hat has to be implemented on top of OpenSSL for a HTTPS client. You will have to implement all three in a HTTP or HTTPS client, unless you need to communicate with only one server and you know it is only using "Content-Length: ####".
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/432079.html
