Tomcat

Apache Tomcat (sau simplu Tomcat, în trecut denumit Jakarta Tomcat) este un web server open source și container servlet dezvoltat de Apache Software Foundation (ASF).
Software-ul Apache Tomcat este dezvoltat într-un mediu deschis și participativ și este lansat sub versiunea 2 a licenței Apache.
Implementează mai multe specificații Java EE, inclusiv Java Servlet , Pagini JavaServer (JSP), Java EL și WebSocket și oferă un mediu server HTTP "pur Java " în care poate rula codul Java .

Tomcat 4.x a fost lansat cu Catalina (un container de servlet), Coyote (un conector HTTP) și Jasper (un motor JSP ).

Catalina

Catalina este containerul de servlet al lui Tomcat . Catalina implementează specificațiile Sun Microsystems pentru servlet și Pagini JavaServer (JSP).

Coyote

Coyote este o componentă Connector pentru Tomcat care acceptă protocolul HTTP 1.1 ca server web. Acest lucru îi permite lui Catalina, denumit în mod obișnuit un servlet Java sau un container JSP, să acționeze și ca un server web simplu care servește fișiere locale ca documente HTTP. Coyote ascultă conexiunile de intrare la server de pe un anumit port TCP și înaintează cererea către Tomcat Engine pentru a procesa cererea și a trimite înapoi un răspuns clientului solicitant. Un alt conector Coyote, Coyote JK, ascultă în mod similar, dar înaintează cererile sale unui alt server web, cum ar fi Apache, folosind protocolul JK . De obicei, aceasta oferă o performanță mai bună.

Jasper

Jasper este motorul JSP al lui Tomcat. Jasper analizează fișierele JSP pentru a le compila în cod Java ca servlets (care pot fi gestionate de Catalina). În timpul execuției, Jasper detectează modificările aduse fișierelor JSP și le va recompila.

Trei componente noi au fost adăugate cu lansarea lui Tomcat 7:

Cluster

Această componentă a fost adăugată pentru a gestiona aplicații mari. Se utilizează pentru echilibrarea încărcării care poate fi obținută prin multe tehnici. Suportul pentru clustering necesită în prezent versiunea JDK 1.5 sau o versiune superioară.

Disponibilitate ridicată

A fost adăugată o funcție de înaltă disponibilitate pentru a facilita programarea actualizărilor de sistem (de exemplu, lansări noi, cereri de modificare) fără a afecta mediul înconjurător. Acest lucru se face prin expedierea cererilor de trafic live către un server temporar pe un port diferit, în timp ce serverul principal este modernizat pe portul principal. Este foarte util pentru a gestiona cererile utilizatorilor pe aplicații web de mare trafic.

Aplicație web

De asemenea, a fost adăugată o îmbunătățire a aplicațiilor web bazate pe utilizator și sistem, pentru a adăuga suport pentru implementare în întreaga gamă de medii.

Instalare

Pentru rularea serviciului avem nevoie ca java să fie inițial instalată. Va fi instalat versiunea 17 a lui jdk deoarece minim acestă versiune este necesară la a compila aplicațiile realizate cu jmix 2.0. Tot din acest motiv se va instala Tomcat versiunea 10 din surse, deoarece în distribuția Ubuntu 22.04 găsim pachetul pentru Tomcat 9.

apt install openjdk-17-jdk

Vom crea un utilizator tomcat și un grup tomcat fără drept de logare cu home în /opt/tomcat

useradd -m -U -d /opt/tomcat -s /bin/false tomcat

Descărcăm aplicația Tomcat și vom fi atenți care este ultima versiune stabilă și vom crea în bash o variabilă VERSIUNE:

VERSIUNE=10.1.17

După ce am creat varibila anterioară folosim wget pentru a descărca Tomcat în directorul cu temporale /tmp:

wget https://www-eu.apache.org/dist/tomcat/tomcat-10/v${VERSIUNE}/bin/apache-tomcat-${VERSIUNE}.tar.gz -P /tmp

Dezarhivăm în directorul /opt/tomcat arhiva descăcată anterior:

tar -xf /tmp/apache-tomcat-${VERSIUNE}.tar.gz -C /opt/tomcat/

Apoi vom crea o legătură simbolică (link) /opt/tomcat/latest la directorul creat anterior prin dezarhivare:

ln -s /opt/tomcat/apache-tomcat-${VERSIUNE} /opt/tomcat/latest

Schimbăm ca proprietarul fișierelor și grupului de care aprțin să fie tomcat create anterior,

chown -R tomcat: /opt/tomcat

și folosind comanda ls -la /opt/tomcat verificăm:

Marcăm ca fiind executabile scripturile din directorul bin:

chmod +x /opt/tomcat/latest/bin/*.sh

Utilizând editorul nano vom crea fișierul tomcat.service în directorul /etc/systemd/system:

nano /etc/systemd/system/tomcat.service

fișier ce va conține următoarele:

[Unit]
Description=Tomcat 10 servlet container
After=network.target

[Service]
Type=forking

User=tomcat
Group=tomcat

Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64"
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom -Djava.awt.headless=true"

Environment="CATALINA_BASE=/opt/tomcat/latest"
Environment="CATALINA_HOME=/opt/tomcat/latest"
Environment="CATALINA_PID=/opt/tomcat/latest/temp/tomcat.pid"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"

ExecStart=/opt/tomcat/latest/bin/startup.sh
ExecStop=/opt/tomcat/latest/bin/shutdown.sh

[Install]
WantedBy=multi-user.target

atenție la calea variabilei JAVA_HOME:

După salvarea și închiderea fișierului vom notifica sistemul systemd de apariția unui nou fișier:

systemctl daemon-reload

Vom porni și vom activa pornirea sistemului la repornirea sistemului:

systemctl enable --now tomcat

Verificăm dacă a pornit servicul tomcat și dacă totul este în ordine:

systemctl status tomcat

Pentru a facilita conectarea din exterior va trebui să realizăm o regulă pentru firewall, folsind editorul nano, în acest caz pentru ufw:

nano /etc/ufw/applications.d/tomcat-server

în care vom scrie următoarele:

[Tomcat]
title=Web server and Java servlet container
description=Apache Tomcat is an web server and java servlet container.
ports=8080/tcp

Utilizând comenzile următoare, vom stabili o nouă regulă de acces:

ufw app list
ufw allow Tomcat
ufw reload

Verificăm dacă noua regulă este încărcată:

ufw status

Cu ajutorul unui browser, în acest caz firefox, verificăm dacă serviciul nostru tomcat este pornit și funcțional:

Cu ajutorul editorului preferat vom configura userul/userii ce are/au drept de administrare:

nano /opt/tomcat/latest/conf/tomcat-users.xml

unde vom specifica utilizatorul, parola și rolurile:

<?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.
-->
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">
<!--
  By default, no user is included in the "manager-gui" role required
  to operate the "/manager/html" web application.  If you wish to use this app,
  you must define such a user - the username and password are arbitrary.

  Built-in Tomcat manager roles:
    - manager-gui    - allows access to the HTML GUI and the status pages
    - manager-script - allows access to the HTTP API and the status pages
    - manager-jmx    - allows access to the JMX proxy and the status pages
    - manager-status - allows access to the status pages only

  The users below are wrapped in a comment and are therefore ignored. If you
  wish to configure one or more of these users for use with the manager web
  application, do not forget to remove the <!.. ..> that surrounds them. You
  will also need to set the passwords to something appropriate.
-->
<!--
  <user username="admin" password="<must-be-changed>" roles="manager-gui"/>
  <user username="robot" password="<must-be-changed>" roles="manager-script"/>
-->
<!--
  The sample user and role entries below are intended for use with the
  examples web application. They are wrapped in a comment and thus are ignored
  when reading this file. If you wish to configure these users for use with the
  examples web application, do not forget to remove the <!.. ..> that surrounds
  them. You will also need to set the passwords to something appropriate.
-->
<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->
   <role rolename="admin-gui"/>
   <role rolename="manager-gui"/>
   <user username="username" password="username_password" roles="admin-gui,manager-gui"/>
</tomcat-users>

repornim serviciul pentru a implementa noile schimbări:

systemctl restart tomcat

Pentru a putea să ne conectăm la pagina web http://ip.ip.ip.ip:8080/manager cu numele utilizatorului și parola setată în etapa anterioară din afara indiferent de ip va trebui să comentăm linia <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> sau să adăugăm ip-ul privilegiat pentru conectare, ca mai jos:

nano /opt/tomcat/latest/webapps/manager/META-INF/context.xml

<?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.
-->
<Context antiResourceLocking="false" privileged="true" >
  <CookieProcessor className="org.apache.tomcat.util.http.Rfc6265CookieProcessor"
                   sameSiteCookies="strict" />
<!--
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|192.168.1.243" />
-->
  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Nu>
</Context>

După modificarea de mai sus, repornim serviciul cu:

systemctl restart tomcat

și vom putea să ne conectăm la pagina de administrare, după introducerea utilizatorului și a parolei definite anterior:

http://ip.ip.ip.ip:8080/manager/html

În aceeași manieră vom proceda și în cazul managerului pentru pagini virtuale ce se regăsește la:

nano /opt/tomcat/latest/webapps/host-manager/META-INF/context.xml

<?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.
-->
<Context antiResourceLocking="false" privileged="true" >
  <CookieProcessor className="org.apache.tomcat.util.http.Rfc6265CookieProcessor"
                   sameSiteCookies="strict" />
<!--
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|192.168.1.243" />
-->
  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Nu>
</Context>

http://ip.ip.ip.ip:8080/host-manager/html

Pentru a avea acces și la documentație din exterior, vom realiza următoarele modificări:

nano /opt/tomcat/latest/webapps/docs/META-INF/context.xml

<?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.
-->
<Context antiResourceLocking="false" >
<!--
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|192.168.1.243" />
-->
</Context>

Securizarea informației se realizează asemenea ca la versiunea 8

Atenție la cale, mai jos căile utilizate sunt pentru versiunea 8.

Deoarece comunicația este în clar iar de obicei tomcat rulează aplicații java ce au acces la baze de date este imperios necesar a se folosi o comunicație criptată/securizată. În acest scop vom folosi chei certificate de Let's Encrypt.
Instalarea clientului și generarea cheilor este descrisă aici.

Cheile generate de Let,s Encrypt le vom copia în directorul ce ține fișierele de configurare a serviciului tomcat:

cp /etc/letsencrypt/live/yo8tff.ro/cert.pem /var/lib/tomcat8/conf
cp /etc/letsencrypt/live/yo8tff.ro/chain.pem /var/lib/tomcat8/conf
cp /etc/letsencrypt/live/yo8tff.ro/privkey.pem /var/lib/tomcat8/conf

Dăm dreptul ca userul sub care rulează tomcat să aibă drept asupra cheilor:

chown tomcat8:tomcat8 /var/lib/tomcat8/conf/*.pem

Edităm fișierul de configurare a serviciului tomcat pentru a porni la portul 8443 o instanță securizată SSL:
nano /etc/tomcat8/server.xml

iar fișierul va arăta sub forma:

<?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 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" />

  <!-- 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 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>

  <!-- 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
   -->
    <!--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 port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               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 port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                         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 port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
               maxThreads="150" SSLEnabled="true" >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
        <SSLHostConfig>
            <Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
                         certificateFile="conf/localhost-rsa-cert.pem"
                         certificateChainFile="conf/localhost-rsa-chain.pem"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>
    -->

<!-- Criptarea SSL a comunicație la portul 8443 -->

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true">
  <SSLHostConfig>
    <Certificate certificateFile="conf/cert.pem"
                 certificateKeyFile="conf/privkey.pem"
                 certificateChainFile="conf/chain.pem" />
  </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 name="Catalina" defaultHost="localhost">

      <!--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 name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="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"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />

      </Host>
    </Engine>
  </Service>
</Server>

Vom reporni serviciul tomcat pentru ca modificările să aibă loc:

systemctl restart tomcat8

După repornire verificăm la adresa domeniului folosind protocol https, portul 8443, folosind browserul preferat dacă serverul a pornit corect și dacă cheile sunt valide: