Showing posts with label Tomcat. Show all posts
Showing posts with label Tomcat. Show all posts

Thursday, 24 September 2009

Creating struts2 login page using Tomcat 6 and JNDI realm

Creating login module when using Struts2 and tomcat can be quite cool and interesting assignement, but can also be a quite annoying job if you are not familiar with all that you need to do…

When creating this module, there are several approaches. For example:

- Creating login module using container managed security
- Creating programmatic login module where you define a “database” of usernames, passwords, and roles. This way you define your login logic by yourself as well.
- Using some 3rd party library

This post describes how to configure Tomcat 6 to support container managed security, using JNDI realm.
I’ll use JNDI realm that enables application server to look for user’s information within Active Directory.

Realms are really cool!
They are, in fact, an instruction  for application server on where to look for user names, passwords and roles when a user that tries to login into your application needs to be authenticated or sometimes it’s a “database” of usernames, password and roles itself.
Great thing when using container managed security is that everything is already implemented, and all you have to do is to provide a realm and map several elements in web.xml, regarding  security.

Let’s start from the beginning.
At this moment, my web.xml file looks like this:


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <session-config>
        <session-timeout>
            15
        </session-timeout>
    </session-config>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

And as for now, I put all my JSPs in the /jsp/ folder.
This is my application structure:

/ - root of  application
/jsp/  - contains JSPs
/css/main.css - contains CSS
/js/jsfile.js  - contains all of my java script code
/images/  - contains a lot of images

My task is to create a login system for this application, and to provide that only logged users , with roles “boss” or “manager” are allowed to se my JSP pages ( located in “/jsp/” folder )

To do that, the first thing we’ll do is to define (add ) roles in our web.xml.
This can be done in some other files as well, but I’ll do it here…
Note: These roles must be equal to those in active directory.

So, let’s add these two roles:

<security-role>
                <role-name>boss</role-name>
        </security-role>
        <security-role>
                <role-name>manager</role-name>
</security-role> 

Next thing we’ll do is to create a security constraint on accessing web pages:

<security-constraint>
                <web-resource-collection>
                        <web-resource-name>Protected area</web-resource-name>
                        <url-pattern>/*</url-pattern>                  
                </web-resource-collection>

                <auth-constraint>
                    <role-name>boss</role-name>
                    <role-name>manager</role-name>
                </auth-constraint>
</security-constraint>

This way, we deny acces to our resources to anyone except to those of  role “boss” or “manager”.

Next thing we need to do is to define the authentication method we will be using.
There are several authentication methods: BASIC, FORM-BASED , DIGEST , SECURE SOCKET LAYER ( SSL) and CLIENT CERTIFICATE AUTHENTICATION.

Which one to use  - depends on what exactly you need.

For us, the most  interesting method is FORM-BASED authentication.
With this method, you create your custom JSP login  form inside your application, with your own look and feel.
There are 3 very important  things to know when working with form-based authentication:

- input field containing user name must be named “j_username”
- input field containing password must be named “j_password”
- action for form containing these two inputs must be “j_security_check”


So, let’s create one!
Here is the example of such page,:

<html>
<head>
<title>Login Page for Examples</title>
<body bgcolor="white">
<form method="POST" action="j_security_check" >
  <table border="0" cellspacing="5">
    <tr>
      <th align="right">Username:</th>
      <td align="left"><input type="text" name="j_username"></td>
    </tr>
    <tr>
      <th align="right">Password:</th>
      <td align="left"><input type="password" name="j_password"></td>
    </tr>
    <tr>
      <td align="right"><input type="submit" value="Log in"></td>
      <td align="left"><input type="reset"></td>
    </tr>
  </table>
</form>
</body>
</html>

Let’s call it “login.jsp”, and place it in the root folder ( /login.jsp )

Now, let’s map it inside web.xml:

<login-config>
                <auth-method>FORM</auth-method>
                <form-login-config>
                        <form-login-page>/login.jsp</form-login-page>

                </form-login-config>
</login-config>

For now, this is good, but it’s not enough.
We also need to define a form-error-page inside a <form-login-config> tag…
Application server will open that page when user enters wrong user name or password.

Here is what I’m going to do:
I’ll define login.jsp page to be form-error-page too, but with result=false in URL.
This way we will know that we need to add some warning message to user that didn’t enter valid username and/or password.
Let’s edit that prevoius <login-config>:

<login-config>
                <auth-method>FORM</auth-method>
                <form-login-config>
                        <form-login-page>/login.jsp</form-login-page>
                        <form-error-page>/login.jsp?result=false</form-error-page>
                </form-login-config>
</login-config>

and let’s edit that login.jsp page, to show error messages when needed:

<html>
<head>
<title>Login Page for Examples</title>
<body bgcolor="white">
                     <%
                         String result = request.getParameter("result");
                         if(result == null)
                            result = "";
                         if (result.equalsIgnoreCase("false")) 
                         {
                    %>
                    <span style="color: red">
                    Wrong user name or password
                    <br>
                    </span>
                    <%       

                         }
                    %>
<form method="POST" action="j_security_check" >
  <table border="0" cellspacing="5">
    <tr>
      <th align="right">Username:</th>
      <td align="left"><input type="text" name="j_username"></td>
    </tr>
    <tr>
      <th align="right">Password:</th>
      <td align="left"><input type="password" name="j_password"></td>
    </tr>
    <tr>
      <td align="right"><input type="submit" value="Log in"></td>
      <td align="left"><input type="reset"></td>
    </tr>
  </table>
</form>
</body>
</html>

So…
We created login.jsp page, we mapped it in the web.xml  and earlier before we made an acces constraint to all of our folders so only logged users can access it.
But now question is: “what if our login page uses some image from /images/ folder in it, or some java script from within /js/ , or css from within /css/ as it  probably would?”

If we leave everything like this, your login form will not be able to read your css and images, and it will look very bad…

What we now need to do is to make some resource  public, so that our login.jsp page could use it…
To do so, we could make some existing folders public ( for example /css/ and /images/ ) ,  or we could copy particular resources ( some images and css that login.jsp needs ) to some new folder and make public only what has to be public ( what we copied ), nothing more…
We’ll do that…
Let’s call this folder “login_resources
Let’s place it in the root:

/login_resources/

Copy all the resources that you login.jsp uses to this folder.
We will now create one more security constraint that will allow everyone ( login.jsp ) to access it:

<security-constraint>
        <web-resource-collection>
        <web-resource-name>Unprotected area</web-resource-name>
        <url-pattern>/login_resources/*</url-pattern>
        </web-resource-collection>
 </security-constraint>

We intentionaly “forgot” to set <auth-constraint> inside <security-constraint> so that everyone could access this resource.

Now, our login form will be able to read all the resources it needs…

And, at the end, we need to add our JNDI  realm to our context.xml file
You could add this realm to some other files as well, but I like to add it to context.xml.

Here is one example of it:

<Realm 
 className="org.apache.catalina.realm.JNDIRealm"
 debug="99"
 connectionURL="ldap://localhost:389"
 userPattern="uid={0},ou=people,dc=mycompany,dc=com"
 roleBase="ou=groups,dc=mycompany,dc=com"
 roleName="cn"
 roleSearch="(uniqueMember={0})"
/>

Please, visit http://tomcat.apache.org/tomcat-6.0-doc/realm-howto.html for more information on creating  realms.
Place this realm inside <context>  </context> tag in context.xml file.

So, let’s sumarize:

Our web.xml now looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">

    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

     <session-config>
        <session-timeout>
            15
        </session-timeout>
    </session-config>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

<security-role>
                <role-name>boss</role-name>
        </security-role>
        <security-role>
                <role-name>manager</role-name>
</security-role> 

<security-constraint>
                <web-resource-collection>
                        <web-resource-name>Protected area</web-resource-name>
                        <url-pattern>/*</url-pattern>                  
                </web-resource-collection>

                <auth-constraint>
                    <role-name>boss</role-name>
                    <role-name>manager</role-name>
                </auth-constraint>
</security-constraint>

<security-constraint>
        <web-resource-collection>
        <web-resource-name>Unprotected area</web-resource-name>
        <url-pattern>/login_resources/*</url-pattern>
        </web-resource-collection>
 </security-constraint>

<login-config>
                <auth-method>FORM</auth-method>
                <form-login-config>
                        <form-login-page>/login.jsp</form-login-page>
                        <form-error-page>/login.jsp?result=false</form-error-page>
                </form-login-config>
</login-config>


Once the user logs in, application server will create a session for him.
You can access it’s user name with

ServletActionContext.getRequest().getUserPrincipal().getName();

or check if he has a sufficient role with

ServletActionContext.getRequest().isUserInRole(“some_role”);


And if you would like to logout, you can use

getRequest().getSession().invalidate();





That’s it for now…
I hope I helped someone and saved him some time...

Sunday, 9 August 2009

Create and use an oracle connection pool in Tomcat 6.xx

NOTE: this post is in fact a translation and a shorter version of post that I wrote on my other blog ( www.baze-podataka.net ). It is translated using Google translate tool and than slightly modified by me. So, if you have any complaints, please complain to Google ;-)

Creating a connection pool is a very good practice when developing applications that often connect to the database because it is much "cheaper" to use one of the already created connections, then to repeat the entire process of Connecting to the database every time we need a connection.
It’s such a good practice that many application servers already have their own implementation of connection pooling.

Such server is Tomcat.

All that is left for us to do, of course, is to set all the properties of server that we need to use, and to provide the appropriate drivers that work with a specific database.
Then, if necessary, just take the connection from the pool, and use it, but take care of their proper use.

In this post, I will set Tomcat 6.0.18.
A database for which I’ll create a connection pool is Oracle 10g.

There’s a lot of tutorials, texts and examples about this on the Internet, but very often related to older versions of Tomcat (ver. 4, 5, 5.5).
Unfortunately, for all of these earlier versions of Tomcat many specifications and settings are different, so it probably won’t work with version 6.xx. At least that was the case with me.

So, let’s create an oracle connection pool!

Prerequisites:
First thing you need to have is , of course, Tomcat.
You can download it following this link.
If you use NetBeans to write a code, as I do, you can use Tomcat that comes bundled with the installation of the IDE itself.

Next, we need the appropriate JDBC drivers for Oracle 10g. This means you need an ojdbc14.jar file that comes within the Oracle itself.

Copy this file to <Tomcat home dir>/lib/ folder.

And, of course, we need a database installed too.
Check whether the database you wish to use is available and whether you can connect to it.

create a connection pool

Creating the pool is a quite fast and easy job.
For example, if your application context path is /myapp , it is necessary for you to:

1. Edit the context.xml file, which is located within the META-INF folder of your project like this:

<?xml version=”1.0? encoding=”UTF-8??>
<Context path=”/myapp” docBase=”myapp” reloadable=”false”>
<Resource name=”jdbc/oracleconnection” auth=”Container”
type=”javax.sql.DataSource” username=”existing_username” password=”user_password”
driverClassName=”oracle.jdbc.driver.OracleDriver” url=”jdbc:oracle:thin:@xxx.xxx.xxx.xxx:1521:sid”
maxActive=”10? maxIdle=”5?/>
</Context>


By setting these parameters you determine how this pool will “look” like.
Visit Tomcat’s website for a list of all available parameters.

2. In the web.xml file of your application, you need to insert:

<resource-ref>
<res-ref-name>jdbc/oracleconnection</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
inside tags <web-app> and </web-app>

And that's it!
Of course, this is not the only way to create connection pool in Tomcat-6, but it is quite simple, don't you think?

Hot to use connections within our web applications

Using connection pool’s connections within our web applications is as easy as creating the pool itself.

In Java EE, DataSource objects are obtained using the JNDI lookup mechanism.
All you need to do to get a connection is something like this:

Connection connection = null;
InitCtx context = new InitialContext ();
EnvCtx context = (Context) initCtx.lookup ( "java:comp/ENV");
DataSource ds = (DataSource) envCtx.lookup ("JDBC/oracleconnection");
connection = ds.getConnection ();

and that’s it.

If you are interested in learning more about connection pool, and the best ways of using it, I suggest you to visit my earlier post , and read the 11th chapter of the book I wrote about...