Is it possible for a site having URL starting with

2020-02-12 05:37发布

问题:

I have a site whose URL starts with "http://" but that is giving me an exception with the message - Unsupported protocol: https. Is it possible that the site is using HTTPS protocol still its URL is starting with "http://" and not "https://".

public ActionForward executeAction(ActionMapping mapping, ActionForm form,
              HttpServletRequest request, HttpServletResponse response)
      throws Exception {

    ActionForward forward = mapping.findForward(Constants.SUCCESS);
    String link = "http://abc.fgh.jkl.mno";
    URL thisURL;
    HttpURLConnection conn = null;
    try {
        thisURL = new URL(link);
        conn = (HttpURLConnection) thisURL.openConnection();
        System.out.println(conn.getResponseCode());
        System.out.println(conn.getResponseMessage());
        } catch (Exception ex) {
        ex.printStackTrace();
    }
    return forward;
}       

Stack trace

java.net.ProtocolException: Unsupported protocol: https'
    at weblogic.net.http.HttpClient.openServer(HttpClient.java:342)
    at weblogic.net.http.HttpClient.New(HttpClient.java:238)
    at weblogic.net.http.HttpURLConnection.connect(HttpURLConnection.java:172)
    at weblogic.net.http.HttpURLConnection.followRedirect(HttpURLConnection.java:643)
    at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:422)
    at           weblogic.net.http.SOAPHttpURLConnection.getInputStream(SOAPHttpURLConnection.java:36)
    at weblogic.net.http.HttpURLConnection.getResponseCode(HttpURLConnection.java:947)
    at com.cingular.cscape.da.struts.action.thisAction.executeAction(thisAction.java:56)
    at com.cingular.cscape.da.struts.action.BaseAction.execute(BaseAction.java:300)
    at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421)
    at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:226)
    at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1164)
    at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:397)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
    at org.extremecomponents.table.filter.AbstractExportFilter.doFilter(AbstractExportFilter.java:53)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3496)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    at weblogic.security.service.SecurityManager.runAs(Unknown Source)
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)                  

回答1:

Did you notice the unmatched apostrophe in the exception message?

java.net.ProtocolException: Unsupported protocol: https'
                                                       ^

Update: looks like this apostrophe is just a quirk of how the WebLogic HttpClient prints this exception.

Asker's root problem was identified in a chat session: he's accessing an http:// URL that redirects him to an https:// URL. The webserver at that https address is serving up a certificate that his JRE/HttpClient does not trust.

The actual exception should be a SSLKeyException. I think the WebLogic HttpClient is misreporting this problem as an unsupported protocol issue. I think the core issue is:

<Warning> <Security> <BEA-090477> javax.net.ssl.SSLKeyException: [Security:090477] Certificate chain received from www.X.com - nnn.nnn.nnn.nnn was not trusted causing SSL handshake failure.

This is the message that the Asker sees when accessing the https:// URL directly (instead of through a redirect chain).

By default Java's Http[s]URLConnection follows redirects automatically and quietly. If you are curious about where you are being redirected to, try this code:

connection.setInstanceFollowRedirects(false);
String location = connection.getHeaderField("Location");
System.out.println("Redirected to: " + location);

Note that the URL you get redirected to may also redirect you somewhere else and on and on, up to http.maxRedirects times. Redirects may "chain" in this way. If they do chain, you will need to keep following the redirects until you reach a URL that does not issue a redirect. That is where the URL connection eventually finalizes when setInstanceFollowRedirects(true).

Also, I found some code in sun.net.www.protocol.http.HttpURLConnection that seems to indicate that HttpURLConnection may not support switching protocols (HTTP -> HTTPS) as part of its automatic redirect following logic:

private boolean followRedirect() throws IOException {
    // ... [snip] ...
    if (!url.getProtocol().equalsIgnoreCase(locUrl.getProtocol())) {
        return false;
    // ... [snip] ...

WebLogic has its own (different) implementation of HttpURLConnection, but it may contain similar logic to prevent protocol switching. So, even if the Asker resolves his certificate trust issues, he still may not be able to use HttpURLConnection to automatically follow a redirect chain that goes from HTTP to HTTPS. A workaround would be to use setInstanceFollowRedirects(false) and follow redirects manually. Or access the HTTPS site directly.



回答2:

HTTP is a protocol that runs on TCP/IP. HTTPS is HTTP on secure socket (SSL or newer TLS). Now, what is a URL? It's a string that identify a resource, and looks roughly like:

scheme://host:port/path/to/resource

Note that sometimes we don't specify the port number, because some protcols have an associated well-known port number. For HTTP is 80, and for HTTPS is 443, so these numbers are implied. However, note that you can bind your server socket on whatever port you want to: if you tell your HTTP server program to bind its socket to the port 8273 on localhost, it will happily do so.

Said that, in your case the message says "unsupported protocol: https". We can just guess here, however I think the string you pass to the URL is not the one you think.



回答3:

Another possibility is the HTTP address responding with a 3xx redirect response to an HTTPS URL, which your client tries to follow, but does not support. You can very by capturing the network traffic with tcpdump or wireshark.

There are so many Java HTTP client libraries that do support HTTPS, why not switch to one of those?



标签: java http https