Apache Tomcat
Setting up Apache Tomcat 9 on Red Hat Linux ES 7.2
Creating first Java Server Page(JSP)
Creating first Servlet
Implementing Tomcat JDBC Realm security
Implementing Tomcat file Realm security
Implementing Tomcat dataSource Realm security
running Apache as proxy for Tomcat
Basic authorization request in curl
Setting up Apache Tomcat 9 on Red Hat Linux ES 7.2
- login as root or sudo to root
- get the distribution and install it using : yum install tomcat
- Determine the port you will be running the webserver and open it in the firewall.Default is 8080.For sake of instruction let's use 8081:
Check open ports: firewall-cmd --list-ports
open a port 8081: firewall-cmd --add-port=8081/tcp --permanent
reload firewall rules: firewall-cmd --reload
Check open ports: firewall-cmd --list-ports
-
Edit server configuration file:
go to installation directory : cd /usr/share/tomcat
go to configuration files directory: cd conf
edit server.xml file : vi server.xml
Find the connector port and change it from 8080 to 8081: Connector port="8081" protocol="HTTP/1.1"
general replace of 8080 to 8081 could look like: 1,$s/8080/8081/g
-
Change the Host name from localhost to the ip address or name of the host, the server is running at:
Host name="192.168.1.220" appBase="webapps"
general replace of localhost could look like: 1,$s/localhost/192.168.1.220/g
-
Close the server configuration file.
-
Create web application structure:
cd /usr/share/tomcat/webapps
create application root directory: mkdir firstapp
change directory to the newly created directory: cd firstapp
create directory for web application code and configuration files: mkdir WEB-INF
create directory for stylesheets: mkdir css
create directory for images: mkdir img
create directory for source files to be compiled into code: mkdir src
change directory to WEB-INF: cd WEB-INF
create directory for java classes:mkdir classes
create directory for CGI scripts and programs: mkdir cgi
-
create index.html file in the web application root directory:
cd /usr/share/tomcat/webapps/firstapp
vi index.html
<HTML>
<HEAD><TITLE>Tomcat first application </TITLE></HEAD>
<BODY>
<H3> Welcome to the firstapp web application running on Tomcat </H3>
</BODY>
</HTML>
-
Start tomcat webserver:
/usr/sbin/tomcat start
-
verify you can see the index page in web browser:
in the address field of your browser type: http://192.168.1.220:8081/firstapp
- Create stylesheet for your website
In css directory of your application create a cba.css file and add the body tag to maintain your site uniformity,e.g:
body {
background-color:#CCCCFF;
}
Creating first Java Server Page(JSP)
-
Change directory to /usr/share/tomcat/webapps/firstapp
-
Create the index.jsp page as following:
<html>
<head><title>First JSP</title>
<link rel="stylesheet" type="text/css" href="css/cba.css">
</head>
<%@ page import="java.util.Date" %>
<body>
<h2>Time is: </h2><%=new Date() %>
<%
double num = Math.random();
if (num > 0.95) {
%>
<h2>Petrol prices will go down</h2>
<%
} else {
>
<h2>Petrol prices will go up</h2>
<%
}
%>
<a href="<%= request.getRequestURI() %>"><h3>Try Again</h3></a>
</body>
</html>
- verify you can see the index.jsp page in web browser:
in the address field of your browser type: http://192.168.1.220:8081/firstapp/index.jsp
- Browse through the code of the underlying servlet generated for your jsp page
sudo to root
change directory to /var/cache/tomcat/work/Catalina
under the hostname or ip address find index_jsp.java and index_jsp.class
in firstapp/org/apache/jsp
This is the code generated and compiled by the Jasper component of Tomcat for your first jsp
Creating your first Tomcat servlet
- change directory to your src: cd /usr/share/tomcat/webapps/firstapp/src
- create a file HelloServlet.java and put the following lines of code there:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class HelloServlet extends HttpServlet {
private String greetingMessage;
private int limit;
private String configMessage;
public void init(ServletConfig config) throws ServletException {
super.init(config);
limit=Integer.parseInt(config.getInitParameter("limit"));
greetingMessage="Hello world of Servlets";
configMessage=config.getServletName();
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<HEAD>");
out.println("<TITLE>Servlet Testing</TITLE>");
out.println("<link rel=stylesheet type=text/css href=css/cba.css>");
out.println("</HEAD>");
out.println("<BODY>");
out.println("<H1>" + greetingMessage +"</H1>");
out.println("<h3>------>" + configMessage + "<-----</h3>");
out.println("<H3> Hi visitor from " + request.getRemoteAddr() + "</H3>");
for(int i=0;i<limit;i++)
{
out.println("Line " + (i+1) +"<BR>");
}
out.println("<h4>If you see this, you, most probably, were lucky to compile your first servlet</h4>");
out.println("</BODY>");
out.println("</HTML>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
- make sure your CLASSPATH includes the tomcat servlet jar:
echo $CLASSPATH
/usr/share/tomcat/lib/tomcat-servlet-3.0-api.jar
- compile the code:
javac -d ../WEB-INF/classes HelloServlet.java
- you can create a makefile in src directory as follows:
default: Hello
Hello:
javac -d ../WEB-INF/classes/ $@Servlet.java
- Make sure your target code in makefile is starting with one tab, not spaces
Now you can compile your servlet from src directory using command: make
- verify the compiled code is in your WEB-INF/classes directory:
ls /usr/share/tomcat/webapps/firstapp/WEB-INF/classes
- In your WEB-INF directory create a Web Application Deployment Descriptor file web.xml with information about your first servlet as follows:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloServlet</servlet-class>
<init-param>
<param-name>limit</param-name>
<param-value>17</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/Hello</url-pattern>
</servlet-mapping>
</web-app>
- Note the limit parameter is set to 17 and the Url pattern is Hello.
- In your browser type in: Host:port/firstapp/Hello
e.g http://192.168.1.220:8081/firstapp/Hello
Implementing Tomcat JDBC Realm security
- put jdbc driver in /usr/share/tomcat/lib, in case of oracle it will be ojdbc7.jar
- Create database tables
Oracle database will be used for this, the usual choice being MySQL, but for Realm purpose they differ only in JDBC driver used
SQLPLUS> create table users(user_name varchar2(20) primary key,user_pass varchar2(20));
SQLPLUS> create table user_roles(user_name varchar2(20),role_name varchar2(20), constraint pk_ro primary key (user_name,role_name) );
- Populate the tables with users and roles data
SQLPLUS>INSERT INTO USERS VALUES('bob','builder');
SQLPLUS>INSERT INTO USER_ROLES VALUES('bob','admin');
- Create a directory for protected files: mkdir /usr/share/tomcat/webapps/firstapp/protected
- create an html file in the created directory, content is left to your imagination:vi /usr/share/tomcat/webapps/firstapp/protected/index.html
- edit server.xml by adding a context tag to the host tag and putting the code inside. This will create realm for only one application, while the others could be using different Realms using MySQL or tomcat_users.xml
<Host name="192.168.1.220" appBase="webapps" unpackWARs="true" autoDeploy="true" >
<Context path="/firstapp">
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="oracle.jdbc.driver.OracleDriver"
connectionURL="jdbc:oracle:thin:@192.168.1.220:1521/pdbcba1"
connectionName="SCOTT" connectionPassword="TIGER"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name" />
</Context>
- edit web.xml for your firstapp application:cd /usr/share/tomcat/webapps/firstapp/WEB-INF
vi web.xml
enter the following lines within the web-app tags:
<security-constraint>
<web-resource-collection>
<web-resource-name>protected</web-resource-name>
<url-pattern>/protected/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
<user-data-constraint>
<!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
- Summary: This will create a realm where usernames and roles will be matched to those in oracle database, and resources located in protected directory of your web application will require a user bob, or any other belonging to admin role to enter the credentials on the first access to resources.
Note: the users can now be added to the database tables without a tomcat restart
Implementing Tomcat dataSource Realm security
- put jdbc driver in /usr/share/tomcat/lib, in case of postgres it will be postgresql-jdbc.jar
- Create database tables
PostgreSQL database will be used for this, the usual choice being MySQL, but for Realm purpose they differ only in JDBC driver used
psql> create table users(user_name varchar2(20) primary key,user_pass varchar2(20));
psql> create table user_roles(user_name varchar2(20),role_name varchar2(20), constraint pk_ro primary key (user_name,role_name) );
- Populate the tables with users and roles data
psql>INSERT INTO USERS VALUES('bob','builder');
psql>INSERT INTO USER_ROLES VALUES('bob','admin');
- Create a directory for protected files: mkdir /usr/share/tomcat/webapps/firstapp/protected
- create an html file in the created directory, content is left to your imagination:vi /usr/share/tomcat/webapps/firstapp/protected/index.html
- In the web aplication directory find or create META-INF directory and edit context.xml file. This will create realm for only one application, while the others could be using different Realms using MySQL or tomcat_users.xml
cd /usr/share/tomcat/webapps/firstapp/META-INF
vi context.xml
<Context>
<Realm className="org.apache.catalina.realm.DataSourceRealm"
localDataSource="true"
dataSourceName="jdbc/postgresadmin"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name" />
< Resource name="jdbc/postgresadmin" auth="Container"
type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://192.168.0.44:5432/cbaadmin"
username="postgres" password="mypassword" maxTotal="20" maxIdle="10" maxWaitMillis="-1" />
</Context>
- edit web.xml for your firstapp application:cd /usr/share/tomcat/webapps/firstapp/WEB-INF
vi web.xml
enter the following lines within the web-app tags:
<security-constraint>
<web-resource-collection>
<web-resource-name>protected</web-resource-name>
<url-pattern>/protected/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
<user-data-constraint>
<!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
<resource-ref>
<description>Postgres login</description>
<res-ref-name>jdbc/postgresadmin</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
- Summary: This will create a realm where usernames and roles will be matched to those in postgresql database, and resources located in protected directory of your web application will require a user bob, or any other belonging to admin role to enter the credentials on the first access to resources.
Note: the users can now be added to the database tables without a tomcat restart
Implementing Tomcat File Realm security
-
locate the tomcat-users.xml file in the apache tomcat conf directory
-
edit it by adding a role and a user to it
<role rolename="admin"/>
<role rolename="employees"/>
<user username="bobby" password="builder" roles="admin,employees"/>
- edit web.xml for your firstapp application:cd /usr/share/tomcat/webapps/firstapp/WEB-INF
vi web.xml
enter the following lines within the web-app tags:
<security-constraint>
<web-resource-collection>
<web-resource-name>protected</web-resource-name>
<url-pattern>/protected/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
<user-data-constraint>
<!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
- Summary: This will create a realm where usernames and roles will be matched to those in tomcat-users.xml file, and resources located in protected directory of your web application will require a user bob, or any other belonging to admin role to enter the credentials on the first access to resources.
Note: Adding the users will require a tomcat restart
using Apache as proxy for Tomcat
- Secure the proxy to only internal net to avoid coin diggers and hackers from using your webserver using CONNECT method
Update httpd.conf by adding a stanza, which will apply to all the virtual hosts
Assumption is that the internal network is 192.168.1.*
<Proxy *>
Order Deny,Allow
Deny from all
Allow from 192.168.1.*
</Proxy>
- Setup the proxy passes inside the VirtualHost stanza, assuming Tomcat is running on localhost:5000
ProxyRequests On
ProxyPass /appdir http://localhost:5000/appdir/
ProxyPassReverse /appdir http://localhost:5000/appdir/
Now you will be able to call the tomcat application by sending request to apache server directory appdir:
https://www.cooolexample.com/apdir
Basic authorization request in curl
- Using login and password for realm
curl https://myserver/myapp/protected/ -u "my_login:my_password"
- Using authorization token
Generate the token in UNIX
echo -n 'my_login:my_password' | base64
curl https://myserver/myapp/protected/ -H "Authorization: Basic bXlfbG9naW46bXlfcGFzc3dvcmQ="
top of the page