Trying to run a simple example of Java NIO SSL to load the contents of https://www.amazon.com but getting 400 Bad Request

huangapple go评论97阅读模式
英文:

Trying to run a simple example of Java NIO SSL to load the contents of https://www.amazon.com but getting 400 Bad Request

问题

尝试了一切但还是不起作用 :(

完整的代码和示例可以在此处找到https://examples.javacodegeeks.com/core-java/nio/java-nio-ssl-example/

此外您可以通过单击此处下载完整的源代码仅有3个类):https://examples.javacodegeeks.com/wp-content/uploads/2015/12/NioSSLExample.zip

感谢任何帮助

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;

public class NioSSLExample
{
   public static void main(String[] args) throws Exception
   {
      InetSocketAddress address = new InetSocketAddress("www.amazon.com", 443);
      Selector selector = Selector.open();
      SocketChannel channel = SocketChannel.open();
      channel.connect(address);
      channel.configureBlocking(false);
      int ops = SelectionKey.OP_CONNECT | SelectionKey.OP_READ;

      SelectionKey key =  channel.register(selector, ops);

      // create the worker threads
      final Executor ioWorker = Executors.newSingleThreadExecutor();
      final Executor taskWorkers = Executors.newFixedThreadPool(2);

      // create the SSLEngine
      final SSLEngine engine = SSLContext.getDefault().createSSLEngine();
      engine.setUseClientMode(true);
      engine.beginHandshake();
      final int ioBufferSize = 32 * 1024;
      final NioSSLProvider ssl = new NioSSLProvider(key, engine, ioBufferSize, ioWorker, taskWorkers)
      {
         @Override
         public void onFailure(Exception ex)
         {
            System.out.println("握手失败");
            ex.printStackTrace();
         }

         @Override
         public void onSuccess()
         {
            System.out.println("握手成功");
            SSLSession session = engine.getSession();
            try
            {
               System.out.println("本地主体:" + session.getLocalPrincipal());
               System.out.println("远程主体:" + session.getPeerPrincipal());
               System.out.println("密码套件:" + session.getCipherSuite());
            }
            catch (Exception exc)
            {
               exc.printStackTrace();
            }

            //HTTP 请求
            StringBuilder http = new StringBuilder();
            http.append("GET / HTTP/1.0\r\n");
            http.append("Connection: close\r\n");
            http.append("\r\n");
            byte[] data = http.toString().getBytes();
            ByteBuffer send = ByteBuffer.wrap(data);
            this.sendAsync(send);
         }

         @Override
         public void onInput(ByteBuffer decrypted)
         {
            // HTTP 响应
            byte[] dst = new byte[decrypted.remaining()];
            decrypted.get(dst);
            String response = new String(dst);
            System.out.print(response);
            System.out.flush();
         }

         @Override
         public void onClosed()
         {
            System.out.println("SSL 会话已关闭");
         }
      };

      // NIO 选择器
      while (true)
      {
         key.selector().select();
         Iterator keys = key.selector().selectedKeys().iterator();
         while (keys.hasNext())
         {
            keys.next();
            keys.remove();
            ssl.processInput();
         }
      }
   }
}
英文:

Trying everyting but it does not work Trying to run a simple example of Java NIO SSL to load the contents of https://www.amazon.com but getting 400 Bad Request

The complete code and example can be found here: https://examples.javacodegeeks.com/core-java/nio/java-nio-ssl-example/

Also you can download the full source (it is only 3 classes) by clicking here: https://examples.javacodegeeks.com/wp-content/uploads/2015/12/NioSSLExample.zip

Thanks for any help!

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
public class NioSSLExample
{
public static void main(String[] args) throws Exception
{
InetSocketAddress address = new InetSocketAddress("www.amazon.com", 443);
Selector selector = Selector.open();
SocketChannel channel = SocketChannel.open();
channel.connect(address);
channel.configureBlocking(false);
int ops = SelectionKey.OP_CONNECT | SelectionKey.OP_READ;
SelectionKey key =  channel.register(selector, ops);
// create the worker threads
final Executor ioWorker = Executors.newSingleThreadExecutor();
final Executor taskWorkers = Executors.newFixedThreadPool(2);
// create the SSLEngine
final SSLEngine engine = SSLContext.getDefault().createSSLEngine();
engine.setUseClientMode(true);
engine.beginHandshake();
final int ioBufferSize = 32 * 1024;
final NioSSLProvider ssl = new NioSSLProvider(key, engine, ioBufferSize, ioWorker, taskWorkers)
{
@Override
public void onFailure(Exception ex)
{
System.out.println("handshake failure");
ex.printStackTrace();
}
@Override
public void onSuccess()
{
System.out.println("handshake success");
SSLSession session = engine.getSession();
try
{
System.out.println("local principal: " + session.getLocalPrincipal());
System.out.println("remote principal: " + session.getPeerPrincipal());
System.out.println("cipher: " + session.getCipherSuite());
}
catch (Exception exc)
{
exc.printStackTrace();
}
//HTTP request
StringBuilder http = new StringBuilder();
http.append("GET / HTTP/1.0\r\n");
http.append("Connection: close\r\n");
http.append("\r\n");
byte[] data = http.toString().getBytes();
ByteBuffer send = ByteBuffer.wrap(data);
this.sendAsync(send);
}
@Override
public void onInput(ByteBuffer decrypted)
{
// HTTP response
byte[] dst = new byte[decrypted.remaining()];
decrypted.get(dst);
String response = new String(dst);
System.out.print(response);
System.out.flush();
}
@Override
public void onClosed()
{
System.out.println("ssl session closed");
}
};
// NIO selector
while (true)
{
key.selector().select();
Iterator keys = key.selector().selectedKeys().iterator();
while (keys.hasNext())
{
keys.next();
keys.remove();
ssl.processInput();
}
}
}
}

答案1

得分: 1

http.append("GET / HTTP/1.0\r\n")
http.append("Connection: close\r\n")
http.append("\r\n")

虽然从理论上讲这是一个正确的 HTTP/1.0 请求但在实际中大多数系统现在要求包含一个 `Host` 头部虽然这只在 HTTP/1.1 下是必需的但如果一个 IP 地址托管多个域名则是必需的

http.append("GET / HTTP/1.0\r\n")
http.append("Host: www.amazon.com\r\n")
http.append("\r\n")

此外请注意 `Connection: close` 是不必要的因为它在 HTTP/1.0 中是隐含的但在 HTTP/1.1 中不是)。

除此之外HTTP 比这个简单的请求复杂得多即使这个请求也有问题正如你所看到的如果你需要自己实现它请阅读标准而不是假设服务器的响应方式或只看一些示例
英文:
        http.append("GET / HTTP/1.0\r\n");
http.append("Connection: close\r\n");
http.append("\r\n");

While this is in theory a correct HTTP/1.0 request in practice, most systems today require that a Host header is included. While this is mandatory only with HTTP/1.1 it is needed if an IP address hosts multiple domains:

        http.append("GET / HTTP/1.0\r\n");
http.append("Host: www.amazon.com\r\n");
http.append("\r\n");

Also note that the Connection: close is unnecessary since it is implicit with HTTP/1.0 (but not with HTTP/1.1).

Apart from that HTTP is way more complex than this simple request and even this one had its problems as you saw. If you need to implement it for yourself please study the standards instead of making assumptions of how servers react or looking only at a few examples.

huangapple
  • 本文由 发表于 2020年4月8日 11:49:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/61093031.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定