Showing posts with label tomcat. Show all posts
Showing posts with label tomcat. Show all posts

Saturday, July 9, 2022

Tomcat Invalid character found in the request target

While running an application in the tomcat server, sometimes we might get the following error.

org.apache.coyote.http11.Http11Processor.service Error parsing HTTP request header
 Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.
	java.lang.IllegalArgumentException: Invalid character found in the request target [/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=md5&vars[1][]=HelloThinkPHP21 ]. The valid characters are defined in RFC 7230 and RFC 3986
		at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:509)
		at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:511)
		at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
		at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831)
		at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1673)
		at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
		at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
		at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
		at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
		at java.lang.Thread.run(Thread.java:748)

First, make sure that the domain pointed to the server is working fine or not expired.

From tomcat, it is suggested that

The HTTP/1.1 specification requires that certain characters are %nn encoded when used in URI query strings. Unfortunately, many user agents including all the major browsers are not compliant with this specification and use these characters in unencoded form. To prevent Tomcat rejecting such requests, this attribute may be used to specify the additional characters to allow. If not specified, no additional characters will be allowed. The value may be any combination of the following characters: " < > [ \ ] ^ ` { | } . Any other characters present in the value will be ignored.

Tomcat increased its security and no longer allows raw square brackets or the above characters in the query string.

In order to resolve this issue use relaxedQueryChars attributes inside the server.xml file of tomcat server. Make sure to back up the server.xml file before we change it.

Open the server.xml file using vim or vi and type Shift + i

sudo vim /path_to_tomcat/conf/server.xml

Press Esc and hit :wq! and save the changes

Restart the tomcat server.

Share:

Friday, July 1, 2022

How to deploy the war file on remote tomcat server

In this tutorial, we are going to learn basic steps to deploy our war file to the tomcat server.

Create a war file:

First, create a war file, this will depend upon the framework used, each framework will provide the command to create a war file. The war file will contain the extension with .war.

Connect to remote server:

Now, let's connect to a remote server where we want to deploy to war file. Here we are SSH connection to the server

If you are using a server password to connect using the following command

sudo ssh server_username@ip_address

Here use your server username and server IP address to connect. For example ubuntu@34.344.56

If you are using a .pem file or other private keys to connect to a server then use the following command

sudo ssh -i path_to_pem_file server_username@ip_address

Download tomcat on the remote server:

Once ssh to a remote server, let's download the tomact server where we will deploy our war file.

Here, we are using tomcat 8 so will download the same.

sudo wget https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.81/bin/apache-tomcat-8.5.81.tar.gz

Extract the file

sudo tar xvzf apache-tomcat-8.5.81.tar.gz

Here, generally, we put the extracted tomcat server under /opt directory of the system.

In this tutorial, we are not using tomcat GUI to make it simple for set up. so let's remove the unnecessary folder from the tomcat server.

sudo rm -r apache-tomcat-8.5.81/webapps/*

Copy war file to remote server:

Now, let's copy the war file to deploy.

sudo scp path_to_war/war_file_name.war server_username@ip_address:~

This will copy the war file into the home directory of the remote server. If you are using .pem file or other private keys then use the following command to copy the war file.

sudo scp -i path_to_pem_file path_to_war/war_file_name.war server_username@ip_address:~

Once the war file is copied and moved to the remote server then, ssh to the remote server if not ssh.

Deploy War file:

First, give sufficient permission for copied war file

sudo chmod 555 war_file_name.war

Copy war file to the webapps directory of our tomcat server

sudo mv war_file_name.war /opt/apache-tomcat-8.5.81/webapps/ROOT.war

Note: make sure that you should copy the war file as ROOT.war inside webapps directory

Install Java:

Tomcat server requires java to run. So let's install java; here, we are using OpenJDK 8 using the following command.

sudo apt-get install openjdk-8-jdk

Confirm the installation

java -version

We can see the similar output

openjdk version "1.8.0_312"
OpenJDK Runtime Environment (build 1.8.0_312-8u312-b07-0ubuntu1~20.04-b07)
OpenJDK 64-Bit Server VM (build 25.312-b07, mixed mode)

Run the Tomcat server:

First, navigate to the tomcat directory and use the below command to run the tomcat server

cd /opt/apache-tomcat-8.5.81/
sudo sh bin/startup.sh

If the tomcat server is running successfully then you are supposed to see the output similar as below

Using CATALINA_BASE:   /opt/apache-tomcat-8.5.81
Using CATALINA_HOME:   /opt/apache-tomcat-8.5.81
Using CATALINA_TMPDIR: /opt/apache-tomcat-8.5.81/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /opt/apache-tomcat-8.5.81/bin/bootstrap.jar:/opt/apache-tomcat-8.5.81/bin/tomcat-juli.jar
Using CATALINA_OPTS:   
Tomcat started.

See the logs of tomcat:

Once Tomcat is running successfully, we need to verify whether the war file is running as expected or not

sudo tail -f logs/catalina.out

This will give the last log file lines; if you want to specify how many lines to view then replace f with e.g 1000 to see the 1000 lines log.

Stop the Tomcat server:

sudo sh bin/shutdown.sh

If the app is running fine, you can open the application using the public IP address or with the domain name if pointed to that IP address.

http://example.com:8080

Or

http://124.56.234:8080

Here, the tomcat server will run with port 8080 by default.

Change the port 8080 to 80:

Under server.xml you can find the following tag.

change the above XML tag as below:

Here, we are changing the port from 8080 to 80 and 8443 to 443. By doing so, if your domain running with port 8080 i.e example.com:8080, now it will open with port 80 i.e example.com. If you type your domain in the browser then you can run it with both HTTP and HTTPS i.e http://example.com and https://example.com.

Save the server.xml file and re-run the tomcat server by first stopping it.

Share:

Tuesday, January 25, 2022

How to Install and configure free SSL/TLS certificate for Tomcat using Let's Encrypt on Ubuntu.

How to set up a free SSL certificate for tomcat using let's encrypt on ubuntu.

1. Introduction:



Here, we are going to set up a free SSL certificate provided by a non-profit authority called Let's Encrypt. This is trusted and used by many to secure their website. The certificate is valid for only 90 days and can renew during that time. You can find out more about Let's Encrypt here

2. Prerequisites:

  • Running ubuntu server
  • Running tomcat server
  • Domain name pointed to the server Ip address

3. Install certbort and create an SSL certificate:
SSH into the server where you want to create a certificate. In order to create an SSL certificate, we need to install certbot for this, go and select the appropriate ubuntu server version from here. As we are using ubuntu 18.04 LTS.


which will give the following command to install certbot.

Add Certbot PPA
 
 sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
Install Certbot
sudo apt-get install certbot
If you have already running service which uses port 80, stop it first otherwise you will get Address BindException.

To obtain an SSL certificate for your domain using a built-in "standalone" webserver type the following command:
sudo certbot certonly --standalone -d example.com
Here, replace the domain name you want to secure instead of example.com 

which will create a different certificate file to the directory:   /etc/letsencrypt/live/example.com/

Now, logged in as root user and go to that directory
sudo -i
cd /etc/letsencrypt/live/example.com/

Next step is to convert those certificate PEM file to password-based PFX format so that we can use in tomcat configuration. We can do this by using OpenSSL command as below.
openssl pkcs12 -export -out bundle.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem -password pass:password
Replace the password with your desired one. It will create a password-protected file bundle.pfx under the same directory "/etc/letsencrypt/live/example.com/" which we need to use in tomcat configuration.





 
4. Tomcat configuration for HTTPs:

Go to your tomcat directory, and backup the server.xml file; as we are going to change the file. It's always a good approach to backup the config file before changing it.
cp conf/server.xml conf/server-copy.xml
 
Edit the server.xml file.
sudo vi conf/server.xml  // no need to type sudo if you are logged in as root user
  
You can see the following xml tag(for tomcat 8), we are going to change this: 



Replace the above tag such that the config look like as below: 


Here, we are changing port 8443 to 443, keystoreType as "PKCS12", keystoreFile as the path of the pfx file created previously and keystorePass as your password that we used while creating PFX file. 

Change the port 8080 to 80: 

Under server.xml you can find the following tag.


change the above xml tag as below:  


Here, we are changing the port from 8080 to 80 and 8443 to 443. By doing so, if your domain running with port 8080 i.e example.com:8080, now it will open with port 80 i.e example.com. If you type your domain in the browser then you can run it with both HTTP and https i.e http://example.com and https://example.com.

Save the server.xml file by clicking "Esc" key and type ":wq!" and hit Enter. 

As we want to always redirect our domain to https. To do so, open the web.xml file under conf/web.xml.
sudo vi conf/web.xml
  
And add the below code at the end of file before the end of "/web-app" xml tag.
<security-constraint>
  <web-resource-collection>
  <web-resource-name>Entire Application</web-resource-name>
   <url-pattern>/*</url-pattern>
 </web-resource-collection>
  <!--auth-constraint goes here if you requre authentication-->
 <user-data-constraint>
 <transport-guarantee>CONFIDENTIAL</transport-guarantee>
 </user-data-constraint>
 </security-constraint>

Which will always redirect to HTTPs.

 
5. Renew certificate:

The certificate is valid for only 90 days so we need to renew before expiry. For this, stop tomcat and type the following command:
sudo certbot renew
 
sudo -i
cd /etc/letsencrypt/live/example.com/
openssl pkcs12 -export -out bundle.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem -password pass:password
 
Don't forget to use your existing password. And restart the tomcat server.

Share:

Saturday, January 22, 2022

Grails 3 Download Saved Documnets/Files (.pdf, .txt, .docx and others) Example.

How to Download different types of files using Grails 3.

If you want to use server-side file download for different types of files like pdf, txt, docx etc then there are different ways to do it.

We can use ServletOutputStream object for it as below:

    def download(){
            def filePath = "/opt/tomcat/webapps/savedFile/filename.pdf" //I am saving files on tomcat.
            def file = new File(filePath)
            if (file.exists()){
                response.setContentType("application/octet-stream")
                response.setHeader("Content-disposition", "filename=${file.getName()}")
                response.outputStream << file.bytes
            }else {
                //handle file not found messages.
            }
}
Here, contentType is "application/octet-stream" for all types of file. If you want to specified for specific one set contentType for specific one.
                response.setContentType("application/pdf")
Or you can do simply like this:

    def download(){
            def filePath = "/opt/tomcat/webapps/savedFile/filename.pdf" //I am saving files on tomcat.
            def file = new File(filePath)
            if (file.exists()){
                response.setContentType("application/octet-stream")
                response.setHeader("Content-disposition", "filename=${file.getName()}")
                response.outputStream << file.newInputStream()
            }else {
                //handle file not found messages.
            }
}
def download(){
            def filePath = "/opt/tomcat/webapps/savedFile/filename.pdf" //I am saving files on tomcat.
            def file = new File(filePath)
            if (file.exists()){
                response.setContentType("application/octet-stream")
                response.setHeader("Content-disposition", "filename=${file.getName()}")
                def outputStream = response.getOutputStream()
                outputStream << file.bytes
                outputStream.flush()
                outputStream.close()
            }else {
                //handle file not found messages.
            }
}
But in grails 3 latter version while deploying the war file to external tomcat(tomcat 7) server then we might get some class not found issue while downloading files.
Error 500: Internal Server Error
URI
/patient/download
Class
java.lang.ClassNotFoundException
Message
Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: javax/servlet/WriteListener
Caused by
javax.servlet.WriteListener
In order to solve this issue, we need to make the controller's action wrap with @GrailsCompileStatic annotation.
import grails.compiler.GrailsCompileStatic

@GrailsCompileStatic
def download(){
            def filePath = "/opt/tomcat/webapps/savedFile/filename.pdf" //I am saving files on tomcat.
            def file = new File(filePath)
            if (file.exists()){
                response.setContentType("application/octet-stream")
                response.setHeader("Content-disposition", "filename=${file.getName()}")
                def outputStream = response.getOutputStream()
                outputStream << file.bytes
                outputStream.flush()
                outputStream.close()
            }else {
                //handle file not found messages.
            }
}
Share:

Wednesday, September 19, 2018

Issue With Tomcat Catalina Permission Denied.

For Tomcat situated on root directory in Linux O.S, tomcat Catalina needs to have permission, and for the user who has run the tomcat may face the issue who does not have required permission to do so. So while running tomcat we may face the similar issues as below:

Using CATALINA_BASE:   /opt/tomcat
Using CATALINA_HOME:   /opt/tomcat
Using CATALINA_TMPDIR: /opt/tomcat/temp
Using JRE_HOME:        /home/kchapagain/spark/jdk1.8.0_101
Using CLASSPATH:       /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar
touch: cannot touch '/opt/tomcat/logs/catalina.out': Permission denied
tomcat/bin/catalina.sh: 415: tomcat/bin/catalina.sh: cannot create /opt/tomcat/logs/catalina.out: Permission denied
In order to resolve this issues one's need to give the permission for that user as:
sudo chown -R kchapagain:kchapagain /opt/tomcat/
Where "kchapagain" is my os user. And my apache-tomcat location is under /opt and apache-tomcat name is "tomcat".

 

Now start tomcat:
sudo kill -9 `pgrep java || echo 1` //run if java is already in used for specific port to avoid address already bind issue.
sh /opt/tomcat/bin/startup.sh
The output will be similar as:
Using CATALINA_BASE:   /opt/tomcat
Using CATALINA_HOME:   /opt/tomcat
Using CATALINA_TMPDIR: /opt/tomcat/temp
Using JRE_HOME:        /home/kchapagain/spark/jdk1.8.0_101
Using CLASSPATH:       /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar
Tomcat started.
Share: