通过Java套接字的HTTPS GET/HTTP/1.1请求
问题描述:
我试图请求使用Java套接字编程的HTTPS页面。我使用的代码是通过Java套接字的HTTPS GET/HTTP/1.1请求
PrintWriter s_out = null;
s_out = new PrintWriter(socketData.getOutputStream(), true);
String message = "GET/HTTP/1.1\r\nHost:stackoverflow.com\r\n";
s_out.println(message);
得到的回答:
HTTP/1.1301MovedPermanentlyLocation:https://stackoverflow.com/X-Request-Guid:b49f01e7-8c3f-4276-b9fe-e325684f0f88Content-Length:143Accept-Ranges:bytesDate:Mon,31Jul201707:15:48GMTVia:1.1varnishConnection:keep-aliveX-Served-By:cache-sin18033-SINX-Cache:MISSX-Cache-Hits:0X-Timer:S1501485348.066340,VS0,VE366Vary:Fastly-SSLX-DNS-Prefetch-Control:offSet-Cookie:prov=929f70a3-e93d-2948-7098-74624f7c4e3c;domain=.stackoverflow.com;expires=Fri,01-Jan-205500:00:00GMT;path=/;HttpOnly<html><head><title>Objectmoved</title></head><body><h2>Objectmovedto<ahref="https://stackoverflow.com/">here</a>.</h2></body></html>
我不知道语法要求在GET/HTTP/1.1\r\nHost:stackoverflow.com\r\n
能否请你所说的其实是调用https页面的语法?
谢谢。
答
该请求看起来“非常正确”,但似乎使用了不安全的连接而不是安全的连接。
基于连接的实现
首先,请考虑使用一个更高层次的抽象,如HttpsURLConnection
(Java Platform SE 8)类。
请看useHttpsConnection()
方法的执行情况。
插座为基础的实施
要建立HTTPS连接SSLSocket
(Java Platform SE 8) 类应当间接使用:实例可以使用SSLSocketFactory
(Java Platform SE 8)类创建。
请看看useSslSocket()
方法的执行情况。
源代码草案(Java 8)
package com.brunov.test.console;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import javax.net.SocketFactory;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
public class Program {
public static void main(final String[] args) throws IOException {
useHttpsConnection();
useSslSocket();
}
/**
* Connection-based implementation.
*/
private static void useHttpsConnection() throws IOException {
final URL url = new URL("https://stackoverflow.com/");
final HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("GET");
try (final InputStream inputStream = connection.getInputStream()) {
final String response = readAsString(inputStream);
System.out.println(response);
}
}
/**
* Socket-based implementation.
*/
private static void useSslSocket() throws IOException {
final SocketFactory socketFactory = SSLSocketFactory.getDefault();
try (final Socket socket = socketFactory.createSocket("stackoverflow.com", 443)) {
final String request = "GET/HTTP/1.1\r\nConnection: close\r\nHost:stackoverflow.com\r\n\r\n";
final OutputStream outputStream = socket.getOutputStream();
outputStream.write(request.getBytes(StandardCharsets.US_ASCII));
final InputStream inputStream = socket.getInputStream();
final String response = readAsString(inputStream);
System.out.println(response);
}
}
/**
* Helper method.
* Read a stream to the end into a string.
*/
private static String readAsString(final InputStream inputStream) throws IOException {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, bytesRead);
}
return outputStream.toString(StandardCharsets.UTF_8.name());
}
}
希望这有助于。
你有什么理由为此任务使用普通的'Socket'?有很多“高级”java API用于在HTTP请求 – zuckermanori
,首先,并且不确定是否相关,您必须使用SSL-Socket而不是普通套接字,因为应该执行其他步骤,执行该步骤为你 - 通过SSL套接字握手,密钥交换,...对吗? – Yazan
@Yazan:是的。访问HTTPS网址时,必须先使用“SSLSocket”并执行SSL/TLS握手,然后才能交换任何与HTTP相关的数据。 –