내장 된 Jetty를 사용하여 샌드 박스 RESTful API를 구축하고 있습니다. 내 증명 설계 : (1) SSL 포트에서 연결을 허용하고 (2) ContextHandlerCollection을 사용하여 URI 접두사를 기반으로 적절한 Handler를 호출하는 간단한 임베디드 부두 (Jetty) 서버.Embedded Jetty : 보안 HTTPS 서버에서 ContextHandler가 http URI로 리디렉션합니다.
간단한 SSL 연결을 사용하여 본인의 원래 테스트가 완벽하게 작동하는 것처럼 보였습니다 (부록의 import 및 helper HelloHandler 클래스 참고). 이 테스트하는 동안
public static void main(String[] args) throws Exception {
Server server = new Server(12000);
ContextHandler test1Context = new ContextHandler();
test1Context.setContextPath("/test1");
test1Context.setHandler(new HelloHandler("Hello1"));
ContextHandler test2Context = new ContextHandler();
test2Context.setContextPath("/test2");
test2Context.setHandler(new HelloHandler("Hello2"));
ContextHandlerCollection contextHandlers = new ContextHandlerCollection();
contextHandlers.setHandlers(new Handler[] { test1Context, test2Context });
server.setHandler(contextHandlers);
server.start();
server.join();
}
그러나, 내가 그렇게 http://localhost:12000/test1
이 http://localhost:12000/test1/
로 리디렉션하기되었으며, 슬래시 뒤에 생략 된 경우 브라우저 리디렉션이 발생하고 있음을 내 관심을 탈출했다. (FWIW, 나중에 4 시간 이상 문제를 해결할 것임).
HTTPS SSL 연결로 전환하면 모든 것이 잘못되었습니다. 아래 코드 :
public static void main(String[] args) throws Exception {
Server server = new Server();
// Setups
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("C:/keystore.jks");
sslContextFactory.setKeyStorePassword("password");
sslContextFactory.setKeyManagerPassword("password");
ContextHandler test1Context = new ContextHandler();
test1Context.setContextPath("/test1");
test1Context.setHandler(new HelloHandler("Hello1"));
ContextHandler test2Context = new ContextHandler();
test2Context.setContextPath("/test2");
test2Context.setHandler(new HelloHandler("Hello2"));
ContextHandlerCollection contextHandlers = new ContextHandlerCollection();
contextHandlers.setHandlers(new Handler[] { test1Context, test2Context });
ServerConnector serverConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, "http/1.1"),
new HttpConnectionFactory());
serverConnector.setPort(12000);
server.setConnectors(new Connector[] { serverConnector });
server.setHandler(contextHandlers);
server.start();
server.join();
}
현상 :
서버가 연결을 재설정 있다고보고 브라우저를 야기 https://localhost:12000/test1
(NO 후행 슬래시)를 사용하려고. 또한 내가 수행 한 작업은 이 아니며 초기에 URI가 http://localhost:12000/test1/
(https가 아님)으로 리디렉션되고 있습니다. 놀랍게도 (가학적인 의미에서 유머 감각을 지닌 방식으로), 몇 차례에 걸쳐 코드에서 중요하지 않은 것을 변경 한 다음 우연히 https://localhost:12000/test1/
으로 테스트하면 작동 할 것입니다. 그러한 거짓 긍정이 야기한 좌절감에 대한 단어는 정의를 지키지 않습니다.
과 연결 재설정 오류를보고, 내 서버 로그에 다음과 같은 예외를 얻을 것입니다 :
2013-11-23 13:57:48 DEBUG org.eclipse.jetty.server.HttpConnection:282 -
org.eclipse.jetty.io.EofException
at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:653)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:240)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:358)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:601)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:532)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at sun.security.ssl.EngineInputRecord.bytesInCompletePacket(EngineInputRecord.java:171)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:845)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:758)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:518)
... 5 more
불행하게도, 내가 직접이 예외를 해결하기 위해 노력하고 나의 모든 시간을 보냈다 , 핵심 단서가 브라우저 리다이렉트 된 URL에있을 때. ContextHandler 코드에는 후행 슬래시가 없을 때 후행 슬래시가있는 URI로 리디렉션되는 기본 동작이 있습니다. 불행히도이 리다이렉트는 HTTP URI에 대한 것이므로 HTTPS 스키마가 삭제되어 서버가 일반 텍스트에 대해 불평을하게됩니다.
해결 방법 :이 리디렉션 행동이 나에게 분명 해졌다되면 해당 실제 문제의 빠른 Google 검색이 ContextHandler.setAllowNullPathInfo (참) 메소드를 알려준
-이 리디렉션 동작을 해제합니다. 인식 할 수없는 SSL : - :이 게시물의test1Context.setAllowNullPathInfo(true);
test2Context.setAllowNullPathInfo(true);
주요 포인트 :은 "(자), javax.net.ssl.SSLException 문제를 해결하려고 4시간 내가 3을 보냈다
위의 내 코드에서,이 2 명 선으로 이루어진다 메시지, 일반 텍스트 연결? " 예외 및 웹 어디에도 위의 솔루션/해결 방법과 관련된 예외가 발견되었습니다. 내가 경험 한 좌절에서 다른 개발자 한 명이라도 저장하면 임무가 완수됩니다.질문을 던지기위한 다른 이유 : 좋아요,이 코드는 작동하지만 고백해야합니다. 믿을 수 없을만큼 간단한 개념 증명 테스트가 내가 흔히 생각하는 것은 완전히 전례가없는 상황을 겪었습니다.그 말은, 나는 아마도 "모범 사례"의 영역을 넘어서 뭔가를하고있을 것이다. 또는, 더 나쁜 것은, 내가 이것을 어떻게 디자인하고 있는지 완전히 잘못되었습니다. 따라서 질문 :
1) 내가 잘못 했나요?
2) 후행 공백이없는 URI를 리디렉션하는 ContextHandler의 기본 동작은 왜입니까? setAllowNullPathInfo (true)를 사용하여 기본 동작을 오버 라이딩하면 어떤 위험이 발생합니까?
부록 (도우미 클래스 및 가져 오기 코드) 수입 : import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.util.ssl.SslContextFactory;
도우미 클래스 :
static class HelloHandler extends AbstractHandler {
final String _greeting;
public HelloHandler(String greeting) {
_greeting = greeting;
}
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
response.getWriter().println("<h1>" + _greeting + "</h1>");
}
}
그것을 맞았다! 그걸 시도해 보았지만 httpConf.addCustomizer (새 SecureRequestCustomizer()) 단계를 생략했습니다. 추가가 영향을 미치지 않아 불필요 해 보였다. – KevinKirkpatrick