Implement https feature using Apache http server

Introduction #

There are at least two options of implementing https for liferay. 1. using a front-end apache http server. 2. using built-in https support in tomcat.

The 2nd option is discouraged.

  • Liferay doesn't allow administrators to configure menu item as https. To work around this, developers would likely have to introduce an extra page with a button directing users to https. From the usability stand point, this is often poorly accepted by users.
  • Once a user in https, there is no way to get back to http - unless the portal source code (not the extension source code) is modified. Modifying the portal source code will complicate the long term maintainability - when we have to upgrade the liferay portal from one version to another. From the software architecture standpoint, this approach is poor designed.

The 1st option solves all the issues mentioned above. Additional benefits are:

  • Majority of the https codes are moved from liferay portal into two apache configuration files. This is a better separation of responsibilities and a far better architecture.
  • If you must take down Liferay server for maintenance, you could use Apache server to display a "maintenance page".
  • This opens up the option of future load balancing & clustering.
  • In theory (I have not tried), you can place the Liferay server in intranet & the Apache server in DMZ. This is securer than placing Liferay server directly in your DMZ.

This document summarizes all the steps of implementing https for liferay using an apache http server.

Implementation #

Assumptions #

  • Apache 2.2 location: C:\Apache2.2
  • Tomcat/Liferay location: D:\projects\liferay5.0.1\tomcat
  • Your web server: jwen
  • Your liferay portal is running on port 8080
  • You have your own signin/signup/change-address pages that you want to secure

Clean up #

If you have already tried the option 2 above, likely you have already had https enabled in tomcat. Before installing Apache, disable https in tomcat first.

  • Open D:\projects\liferay5.0.1\tomcat\conf\server.xml
  • commented out the line below " <!-- Define a SSL HTTP/1.1 Connector on port"

As we will use Apache to take over port 80, make sure liferay is using port 8080.

  • Open D:\projects\liferay5.0.1\tomcat\conf\server.xml
  • Find "<!-- Define a non-SSL HTTP/1.1 Connector on port"
  • Make sure the port attribute below is 8080

Verification

  • Open web browser. Make sure you do get result from https://jwen:8080
  • Open web browser. Make sure you do NOT get any result from https://jwen:443

Install Apache http server - http #

  • If you are using Windows, you should get http://apache.wildit.net.au/httpd/binaries/win32/apache_2.2.9-win32-x86-openssl-0.9.8h-r2.msi
  • Install it under C:\Apache2.2
  • Verify the port that Apache is listening
    • Open C:\Apache2.2\conf\httpd.conf
    • Search for "#Listen". Below that line there should be sometime like "Listen 80". Change that if you need to ( catch 1 )

Verification

  • Open web browser. Make sure you do get "It works!" from http://jwen:80/

Install Apache http Server - https #

  • Create a self-signed certificate following this document http://www.akadia.com/services/ssh_test_certificate.html . After the steps above, you should have two files (server.crt & server.key) under C:\Apache2.2\conf
  • Enable mod_ssl for apache, and load additional configuration file for https. Change the following lines in C:\Apache2.2\conf\httpd.conf

from

   #LoadModule ssl_module modules/mod_ssl.so
   #Include conf/extra/httpd-ssl.conf

to

   LoadModule ssl_module modules/mod_ssl.so
   Include conf/extra/httpd-ssl.conf
  • Make sure https is listening port 443. Open C:\Apache2.2\conf\extra\httpd-ssl.conf. You should find "Listen 443"
  • In C:\Apache2.2\conf\extra\httpd-ssl.conf, you may or may not need to change the certicate file/key value
SSLCertificateFile "C:/Apache2.2/conf/server.crt"
SSLCertificateKeyFile "C:/Apache2.2/conf/server.key"

Verification

  • Open web browser. Make sure you do get "It works!" from https://jwen:443/

Hook Apache to Liferay - mod_proxy #

  • Open C:\Apache2.2\conf\httpd.conf
  • Uncomment the following lines
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
  • Added the following line at the very bottom of the page
ProxyRequests On

ProxyPass / http://jwen:8080/
ProxyPassReverse / http://jwen:8080/

Verification

  • Open web browser. If you can get to liferay page via https://jwen:80/, it means Apache hooks port 80 to your liferay portal port 8080 already.

Secure pages you want to secure #

  • Open C:\Apache2.2\conf\httpd.conf
  • Add the following lines before the "ProxyRequests On" line
RewriteEngine On

#forces everything under /web/guest/signup to secure if non-secure (https)
RewriteCond %{SERVER_PORT} =80
RewriteRule ^(/web/guest/signup.*)$ https://%{SERVER_NAME}:443$1 [R,L]
RewriteRule ^(/web/guest/change-of-details.*)$ https://%{SERVER_NAME}:443$1 [R,L]
RewriteRule ^(/c/portal/login.*)$ https://%{SERVER_NAME}:443$1 [R,L]

Un-secure pages you do not want to secure #

  • Open C:\Apache2.2\conf\extra\httpd-ssl.conf
  • Add the following lines above the "</VirtualHost>"
RewriteEngine on

#forces everything not under /web/guest/signup to non-secure if secure (http)
RewriteCond %{SERVER_PORT} =443
RewriteCond %{REQUEST_URI} !^/(web/guest/signup.*)$
RewriteCond %{REQUEST_URI} !^/(web/guest/change-of-details.*)$
RewriteCond %{REQUEST_URI} !^/(c/portal/login.*)$
RewriteCond %{REQUEST_URI} !^/(c/.*)$
RewriteCond %{REQUEST_URI} !^/(html/.*)$
RewriteRule ^(.*)$ http://%{SERVER_NAME}:80$1 [R,L]

Note that the following two lines are very important. Without them your users would see the security warning "You have requested an encrypted page that contains some unencrypted information. Information that you see or enter on this page could easily be read by a third party."

RewriteCond %{REQUEST_URI} !^/(c/.*)$
RewriteCond %{REQUEST_URI} !^/(html/.*)$

Secure form post #

By default, the jsp forms are post via http. Switching them to https is fairly simple (remember that you only need to secure a very limited number of jsp pages).

Change

<portlet:actionURL>

to

<portlet:actionURL secure="true">

Catches #

Catch 1 - Port 80 #

After you hooked apache to liferay via port 80, your server may or may not be extremly slow. If it is the case, try the following

  • Change port 80 to another port like 8081
  • Change the implementation to another server, and see if it is reproduciable.

The cause of this is unknow at this moment.

Catch 2 - Certificate extension #

If you are relative new to certificates, pay close attention to the certificate files' extensions. ".crt", ".cer", ".csr".

Catch 3 - Modify Apache config files #

Each time after you modified the Apache config files, you need to do the following two things.

  • Restart Apache.
  • Refresh your browser using Ctrl-F5

Catch 4 - Users redirected to liferay instead of Apache #

Users should interactife with Apache (http://jwen/). There are three cases that they may be wrongly redirected to liferay (http://jwen:8080).

  • Case 1: Your company logo at the top-left of your browser
  • Case 2: The "Home" link at the top-right cornor of your browser
  • Case 3: After a new user clicks to accept the terms & conditions.

To fix these,

  • Case 1: Modify D:\projects\liferay5.0.1\ext\ext-web\docroot\html\themes\classic\templates\portal_normal.vm

Change

<a class="png" href="$company_url">$company_name</a>

to

<a class="png" href="/web/guest/">$company_name</a>
  • Case 2: Modify D:\projects\liferay5.0.1\ext\ext-web\docroot\html\themes\classic\templates\dock.vm

Change

<a href="$home_url">$home_text</a>
<a href="/web/guest/">$home_text</a>
  • Case 3: Copy the term & condition jsp page from portal source to D:\projects\liferay5.0.1\ext\ext-web\docroot\html\portal\terms_of_use.jsp

Change

<input name="<%= WebKeys.REFERER %>" type="hidden" 
value="<%= themeDisplay.getPathMain() %>/portal/layout?doAsUserId=<%= themeDisplay.getDoAsUserId() %>" />

to

<input name="<%= WebKeys.REFERER %>" type="hidden" value="/web/guest/" />

Take note that I am using the classic theme. Your theme may be different. Your home link may or may not be the same as mine.

Catch 5 - Apache & Liferay in two different Servers #

Let's say your apache is in a virtual server named "mockingbird", and your liferay is in a virtual server named "flamingo"

To make it work, you need to add the following lines to D:\projects\liferay5.0.1\ext\ext-impl\src\portal-ext.properties

#
# Web Server - public (fronted) web
#
web.server.host=flamingo

or

#
# Web Server - public (fronted) web
#
web.server.host=flamingo.yourdomain.com

I also have the following lines in the file

#
# Set ports for http server
#
web.server.http.port=80
web.server.https.port=443

Conclusion #

If you have followed all of the steps in this guide, it should work. Feel free to contact me if you have any question. Wish you all the fun!

John Wen
Sun Certified Enterprise Architect
Email: JohnXWen@Yahoo.Com
0 Attachments
47512 Views
Average (2 Votes)
The average rating is 4.5 stars out of 5.
Comments
Threaded Replies Author Date
Hi, thanks for this in-depth posting. I'd... Olaf Kock October 16, 2008 7:35 AM
Hi, is this guideline still valid for liferay... Pietro Piccoli February 9, 2012 12:19 AM

Hi,

thanks for this in-depth posting. I'd like to add without destroying the documents structure and content.

I've usually had very good success with mod_jk2, which requires tomcat to listen with an Ajp13-Connector, usually on port 8009. This utilizes another protocol (ajp) for server-to-server-communication, that has the benefit of tomcat knowing the original URL that the request was posted to. Therefor I believe that Catch 4 will not be an issue (though I currently cannot guarantee this)

An alternative solution for Catch 4, using mod_proxy, but also not yet tested with Liferay is to make the proxying known to tomcat by setting the http connectors properties 'proxyName' and 'proxyPort' as documented here: http://tomcat.apache.org/tomcat-6.0-doc/config/http.html. This makes the original request properties known to tomcat and usually helps. (Again: Caution - I've not yet tested this with Liferay, but am confident that it helps removing the root cause for catch 4)

Also, I'm strongly opposing mixing https and http. It's a lot easier to just enable https and forget about conditions when you want your users to go back to http. Session cookies cannot be marked 'secure' with this configuration. That means, that even though passwords are sent encrypted, the user is prone to session hijacking because their session id might be transmitted in the clear once the requests revert from https to http. See also my reasoning in two of todays forum posts at http://www.liferay.com/c/message_boards/find_message?messageId=1443137 (and below)
Posted on 10/16/08 7:35 AM.
Hi,
is this guideline still valid for liferay 6.1 version or is there a different way to get https works for login form only if I have this configuration:
Browser -> Apache -> Tomcat 7.0.25/Liferay 6.1?


Thanks in advance.
Posted on 2/9/12 12:19 AM.