Window 10 让 tomcat 9 在 https 上工作

Window 10 Getting tomcat 9 to work on https

我的目标是使用 java 脚本 webkitGetUserMedia 访问网络摄像头并在我的 LAN 网络上使用 java WebSocket。我将 apache-tomcat-9.0.20 与 apache-maven-3.6.3 和 eclipse ide 一起使用。我可以很好地访问我网络上的 http。但是,使用 https 我只能访问服务器本身。我尝试关闭防火墙,将默认主机名更改为服务器计算机名。但没有任何效果。请记住,网络摄像头需要 https 才能使用,我可以通过将 jsp 更改为 php 在我的网络中使用我的代码和 apache 服务,所以我真的怀疑它是防火墙问题。

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
--><!-- Note:  A "Server" is not itself a "Container", so you may not
     define subcomponents such as "Valves" at this level.
     Documentation at /docs/config/server.html
 --><Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>

  <!-- Global JNDI resources
       Documentation at /docs/jndi-resources-howto.html
  -->
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
  </GlobalNamingResources>

  <!-- A "Service" is a collection of one or more "Connectors" that share
       a single "Container" Note:  A "Service" is not itself a "Container",
       so you may not define subcomponents such as "Valves" at this level.
       Documentation at /docs/config/service.html
   -->
  <Service name="Catalina">

    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <!--
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>
    -->


    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
    -->
    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
    <!-- A "Connector" using the shared thread pool-->
  
    <Connector connectionTimeout="20000" executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
  
    <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443
         This connector uses the NIO implementation. The default
         SSLImplementation will depend on the presence of the APR/native
         library and the useOpenSSL attribute of the
         AprLifecycleListener.
         Either JSSE or OpenSSL style configuration may be used regardless of
         the SSLImplementation selected. JSSE style configuration is used below.
    -->
  
    <Connector SSLEnabled="true" maxThreads="150" port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol">
    </Connector>

    <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
         This connector uses the APR/native implementation which always uses
         OpenSSL for TLS.
         Either JSSE or OpenSSL style configuration may be used. OpenSSL style
         configuration is used below.
    -->
   
    <Connector SSLEnabled="true" maxThreads="150" port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol">
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/>
        <SSLHostConfig>
            <Certificate certificateChainFile="C:\Users\spjpi\Desktop\localhost.pkipath" certificateFile="C:\Users\spjpi\Desktop\localhost.cer" certificateKeyFile="C:\Users\spjpi\Desktop\localhost.pem" type="RSA"/>
        </SSLHostConfig>
    </Connector>
  

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>


    <!-- An Engine represents the entry point (within Catalina) that processes
         every request.  The Engine implementation for Tomcat stand alone
         analyzes the HTTP headers included with the request, and passes them
         on to the appropriate Host (virtual host).
         Documentation at /docs/config/engine.html -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie :
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
    -->
    <Engine defaultHost="localhost" name="Catalina">

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->

      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
      </Realm>

      <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->

        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t &quot;%r&quot; %s %b" prefix="localhost_access_log" suffix=".txt"/>

      <Context docBase="camera" path="/camera" reloadable="true" source="org.eclipse.jst.j2ee.server:camera"/></Host>
    </Engine>
  </Service>
</Server>

首先,在您的示例配置中,您多次注册相同的端口(2x8080 和 2x8443),因此您的服务器将在您的控制台中抛出错误。

确保每个端口只注册一个连接器。换句话说,你会得到这样的例外:

27-Feb-2020 01:56:22.744 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]<br>
27-Feb-2020 01:56:22.783 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]<br>
27-Feb-2020 01:56:22.795 SEVERE [main] org.apache.catalina.util.LifecycleBase.handleSubClassException Failed to initialize component [Connector[HTTP/1.1-8080]]<br>
    org.apache.catalina.LifecycleException: Protocol handler initialization failed
        at org.apache.catalina.connector.Connector.initInternal(Connector.java:983)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        at org.apache.catalina.core.StandardService.initInternal(StandardService.java:533)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:1059)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:584)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:621)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:344)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:475)
    Caused by: java.net.BindException: Address already in use
        at sun.nio.ch.Net.bind0(Native Method)
        at sun.nio.ch.Net.bind(Net.java:433)
        at sun.nio.ch.Net.bind(Net.java:425)
        at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
        at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
        at org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:248)
        at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:222)
        at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1119)
        at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1132)
        at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:557)
        at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:74)
        at org.apache.catalina.connector.Connector.initInternal(Connector.java:980)<br>
        ... 13 more

因此,您应该 select 端口 8080 的以下配置之一:

    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
    -->
    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
    <!-- A "Connector" using the shared thread pool-->
  
    <!--<Connector connectionTimeout="20000" executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>-->

Or With a shared thread pool:
  
    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
    -->
    <!--<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>-->
    <!-- A "Connector" using the shared thread pool-->
  
    <Connector connectionTimeout="20000" executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

类似情况,使用 SSL 端口 8443:

        <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses 
            the NIO implementation. The default SSLImplementation will depend on the 
            presence of the APR/native library and the useOpenSSL attribute of the AprLifecycleListener. 
            Either JSSE or OpenSSL style configuration may be used regardless of the 
            SSLImplementation selected. JSSE style configuration is used below. -->

        <Connector SSLEnabled="true" maxThreads="150" port="8443"
            protocol="org.apache.coyote.http11.Http11NioProtocol">
            <SSLHostConfig>
                <Certificate
                    certificateChainFile="C:\Users\spjpi\Desktop\localhost.pkipath"
                    certificateFile="C:\Users\spjpi\Desktop\localhost.cer"
                    certificateKeyFile="C:\Users\spjpi\Desktop\localhost.pem"
                    type="RSA" />
            </SSLHostConfig>
        </Connector>

        <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2 This 
            connector uses the APR/native implementation which always uses OpenSSL for 
            TLS. Either JSSE or OpenSSL style configuration may be used. OpenSSL style 
            configuration is used below. -->

        <!--<Connector SSLEnabled="true" maxThreads="150" port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol">
            <UpgradeProtocol
                className="org.apache.coyote.http2.Http2Protocol" />
            <SSLHostConfig>
                <Certificate
                    certificateChainFile="C:\Users\spjpi\Desktop\localhost.pkipath"
                    certificateFile="C:\Users\spjpi\Desktop\localhost.cer"
                    certificateKeyFile="C:\Users\spjpi\Desktop\localhost.pem"
                    type="RSA" />
            </SSLHostConfig>
        </Connector>-->

使用 Http/2 协议:

        <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses 
            the NIO implementation. The default SSLImplementation will depend on the 
            presence of the APR/native library and the useOpenSSL attribute of the AprLifecycleListener. 
            Either JSSE or OpenSSL style configuration may be used regardless of the 
            SSLImplementation selected. JSSE style configuration is used below. -->

        <!--<Connector SSLEnabled="true" maxThreads="150" port="8443"
            protocol="org.apache.coyote.http11.Http11NioProtocol">
            <SSLHostConfig>
                <Certificate
                    certificateChainFile="C:\Users\spjpi\Desktop\localhost.pkipath"
                    certificateFile="C:\Users\spjpi\Desktop\localhost.cer"
                    certificateKeyFile="C:\Users\spjpi\Desktop\localhost.pem"
                    type="RSA" />
            </SSLHostConfig>
        </Connector>-->

        <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2 This 
            connector uses the APR/native implementation which always uses OpenSSL for 
            TLS. Either JSSE or OpenSSL style configuration may be used. OpenSSL style 
            configuration is used below. -->

        <Connector SSLEnabled="true" maxThreads="150" port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol">
            <UpgradeProtocol
                className="org.apache.coyote.http2.Http2Protocol" />
            <SSLHostConfig>
                <Certificate
                    certificateChainFile="C:\Users\spjpi\Desktop\localhost.pkipath"
                    certificateFile="C:\Users\spjpi\Desktop\localhost.cer"
                    certificateKeyFile="C:\Users\spjpi\Desktop\localhost.pem"
                    type="RSA" />
            </SSLHostConfig>
        </Connector>

有效的示例配置(使用我自己的密钥库)可以是:

    <?xml version="1.0" encoding="UTF-8"?>
    <!--
      Licensed to the Apache Software Foundation (ASF) under one or more
      contributor license agreements.  See the NOTICE file distributed with
      this work for additional information regarding copyright ownership.
      The ASF licenses this file to You under the Apache License, Version 2.0
      (the "License"); you may not use this file except in compliance with
      the License.  You may obtain a copy of the License at
    
          http://www.apache.org/licenses/LICENSE-2.0
    
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.
    -->
    <Server port="8005" shutdown="SHUTDOWN">
      <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
      <!--APR library loader. Documentation at /docs/apr.html -->
      <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
      <!-- Prevent memory leaks due to use of particular java/javax APIs-->
      <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
      <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
      <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
    
      <GlobalNamingResources>
        <!-- Editable user database that can also be used by
             UserDatabaseRealm to authenticate users
        -->
        <Resource name="UserDatabase" auth="Container"
                  type="org.apache.catalina.UserDatabase"
                  description="User database that can be updated and saved"
                  factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
                  pathname="conf/tomcat-users.xml" />
      </GlobalNamingResources>
    
      <Service name="Catalina">
    
        <!--The connectors can use a shared executor, you can define one or more named thread pools-->
        <!--
        <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
            maxThreads="150" minSpareThreads="4"/>
        -->
    
        <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
        
        <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
                   maxThreads="150" SSLEnabled="true">
            <SSLHostConfig>
                <Certificate certificateKeystoreFile="/Users/myuser/dev/keystore/keystore-dev.jks"
                  certificateKeyAlias="localhost" certificateKeystorePassword="localhost"
                             type="RSA" />
            </SSLHostConfig>
        </Connector>
    
        <!-- Define an AJP 1.3 Connector on port 8009 -->
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    
        <Engine name="Catalina" defaultHost="localhost">
    
          <!-- Use the LockOutRealm to prevent attempts to guess user passwords
               via a brute-force attack -->
          <Realm className="org.apache.catalina.realm.LockOutRealm">
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                   resourceName="UserDatabase"/>
          </Realm>
    
          <Host name="localhost"  appBase="webapps"
                unpackWARs="true" autoDeploy="true">
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                   prefix="localhost_access_log" suffix=".txt"
                   pattern="%h %l %u %t &quot;%r&quot; %s %b" />
          </Host>
        </Engine>
      </Service>
    </Server>

如果一切配置正常,启动服务器,您将在日志中看到如下内容:

27-Feb-2020 02:15:14.234 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
27-Feb-2020 02:15:14.268 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["https-jsse-nio-8443"]
27-Feb-2020 02:15:14.473 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["ajp-nio-8009"]
27-Feb-2020 02:15:14.475 INFO [main] org.apache.catalina.startup.Catalina.load Server initialization in [828] milliseconds
27-Feb-2020 02:15:14.500 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
27-Feb-2020 02:15:14.500 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/9.0.20]
....
27-Feb-2020 02:15:15.144 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
27-Feb-2020 02:15:15.158 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["https-jsse-nio-8443"]
27-Feb-2020 02:15:15.164 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]
27-Feb-2020 02:15:15.166 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [690] milliseconds

之后,从浏览器或命令行(使用 curl、wget 等)在本地测试您的服务器:

  1. https://localhost:8443/

  2. https://127.0.0.1:8443/

  3. https://YOUR_IP:8443/(其中YOUR_IP是您的服务器IP,例如192.168.0.1)

如果您的证书是自签名证书(供开发使用)或未由受信任的机构签名,您将在浏览器中收到如下错误:“您的连接不是私有的”(例如 ERR_CERT_AUTHORITY_INVALID). 因此,您需要将您的证书放在受信任的证书存储中,接受不安全的证书,或使用由受信任的机构签署的生产就绪证书(有关此的更多信息:solve invalid SSL/TLS issue)。

请记住,默认情况下 tomcat 连接器将侦听所有本地服务器地址。

For your information, if you want to restrict the binding IP addresses, the connector has an 'address' attribute that you can specify with the IP.

来自 Tomcat 参考:docs

地址

For servers with more than one IP address, this attribute specifies which address will be used for listening on the specified port. By default, the connector will listen all local addresses. Unless the JVM is configured otherwise using system properties, the Java based connectors (NIO, NIO2) will listen on both IPv4 and IPv6 addresses when configured with either 0.0.0.0 or ::. The APR/native connector will only listen on IPv4 addresses if configured with 0.0.0.0 and will listen on IPv6 addresses (and optionally IPv4 addresses depending on the setting of ipv6onlyv6) if configured with ::.

如果您无法使用提供的此 url 在本地访问您的服务器,请提供您的日志和错误消息。

否则,如果您在本地成功访问所有这些 url,请从远程主机尝试:

  1. 检查服务器 IP 是否可以从远程终端访问(例如 ping)
  2. 尝试在浏览器中访问 https://YOUR_IP:8443/(和 http://YOUR_IP:8080/)
  3. 如果您收到错误消息“您的连接不是私人连接”,请按查看更多详细信息并接受继续不安全。在这种情况下,如前所述,请检查您的证书是否 valid/not 已过期并且权限在您受信任的证书中。
  4. 如果您遇到另一种错误,请检查您的服务器和远程 client/pc 是否已禁用防火墙规则(双方)并使用 telnet 检查远程端口访问。
  5. 检查您的 /etc/hosts 和 iptables 配置。
  6. 如果问题仍然存在,请提供更多信息。

希望对您有所帮助,