Попытка запустить простой пример Java NIO SSL для загрузки содержимого https://www.amazon.com, но при получении 400 Bad Request - PullRequest
0 голосов
/ 08 апреля 2020

Пробует все, но это не работает: (

Полный код и пример можно найти здесь: 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("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 голос
/ 08 апреля 2020
        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 намного сложнее, чем этот простой запрос, и даже у этого, как вы видели, были свои проблемы. Если вам нужно реализовать это для себя, изучите стандарты, а не делайте предположения о том, как реагируют серверы, или рассматривайте только несколько примеров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...