• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 536
  • Last Modified:

User Authentication - and Struts :)

Hi,
   This is another one of my famous advice questions I'm afraid :)

   I'm putting an app together using Struts and Hibernate - so far that side of things is going swimmingly well. Now it's time to add basic authentication to it. When a user is not logged in, they are classed as a"guest" and can access some services but not many. If a user is signed in, they can access all the features of the site.

   What I'm looking for is opinions on the best way of handling authentication in this way. I haven't had to do it before and I figured it would be best to ask the experts on how they'd do it :)

   I look forward to hearing from everyone :)



PS The high points is because usually a lot of people reply - I try to dish them out fairly across the board but if you're really concerned about getting points, you might wanna sit this one out hehe :)
0
petepalmer
Asked:
petepalmer
  • 8
  • 6
1 Solution
 
TimYatesCommented:
I do it by storing usernames and encrypted passwords in a database table.  

Then, when the user logs in, encrypt their password, and compare it with the one in the database.

If login is successful, I add a flag to their session saying that they are logged in, and what level of user they are.

Then, I have an Tomcat Listener which listens to all HTTP requests, and a list of pages, and which types of users can access them.

This checks the page you are looking it, the rights you need and the rights you have (out of your session), and redirects you to a "Invalid page" page if your rights are not high enough.

I also have a jsp which builds the site menu/map dependant on your logged in status.

That's how I do it...  It could be neater I guess...but it kinda evolved over the space of a few months ;-)

Tim
0
 
petepalmerAuthor Commented:
I was thinking along the same lines but having a user object in the session which would have various methods for example isAdmin()

My menu page is just a basic jsp - I guess I should upgrade that :)


You said you encrypted the password - MD5 hash?
0
 
TimYatesCommented:
>> having a user object in the session which would have various methods for example isAdmin()

Actually, that's *exactly* what I've got too :-D

>> You said you encrypted the password - MD5 hash?

Yeah, MD5 hash, but I do a hash on

  username + "a fixed string of my own choosing" + password

so that users with the same password don't get the same hash :-)

It's not 100% secure (as there are MD5 collisions found), but it's better than plain text ;-)
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
petepalmerAuthor Commented:
Sounds like a plan :)

Any pitfalls that I should look out for ?
0
 
TimYatesCommented:
Dont forget the Listener will get called for all images/classes/everything  not just jsp's or *.do pages...

That's all I can think of for now :-/

Oh, and because you save the user in the session, if you upgrade a user to a better/worse level, they have to log out and back in again before any changes take effect...
0
 
petepalmerAuthor Commented:
Listener?  *innocent look*


I have a context listener so I know about those :)
0
 
TimYatesCommented:
Something like this:

This only checks that the person is logged in, it has no concept of access levels...that can be an exercise for you ;-)

It will involve writing the code to replace the

          valid = CHECK TO SEE IF THIS USER CAN ACCESS THIS PAGE

bit... ;-)

hehehehehe

I hope this works, I have had to chop it about out of my code (to get rid of stuff you don't need)

Basically, save this as

org/webproject/filters/LoggedInFilter.java

compile it, and copy it to

WEB-INF/classes/org/webproject/filters

and add the following lines to WEB-INF/web.xml

  <filter>
    <filter-name>login</filter-name>
    <filter-class>org.picr.mvwa.filters.LoggedInFilter</filter-class>
  </filter>
...
  <filter-mapping>
    <filter-name>login</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

As you can see...when it fails, and sends you to "Welcome.do", it stores the URI you were trying to access in "RedirectOnLogin" in the session...

So when you log in, you can redirect the user to this URI, and they will go to where they were trying to get to ;-)

As I said, there is no "level based" access loggin in this...  basically, you succeed or fail, but hopefully this will give you a good base to start from, to add your level based access to :-)

Tim

-------------

package org.webproject.filters ;

import java.io.IOException ;
import java.util.StringTokenizer ;
import java.util.Vector ;
import javax.servlet.Filter ;
import javax.servlet.FilterChain ;
import javax.servlet.FilterConfig ;
import javax.servlet.ServletException ;
import javax.servlet.ServletRequest ;
import javax.servlet.ServletResponse ;
import javax.servlet.http.HttpServletRequest ;
import javax.servlet.http.HttpServletResponse ;
import javax.servlet.http.HttpSession ;

import org.apache.commons.logging.Log ;
import org.apache.commons.logging.LogFactory ;

public class LoggedInFilter implements Filter
{
  private static Log log = LogFactory.getLog( LoggedInFilter.class ) ;

  private FilterConfig filterConfig;

  public void doFilter( final ServletRequest request,
                        final ServletResponse response, FilterChain chain ) throws
                        IOException, ServletException
  {
    HttpServletRequest req = (HttpServletRequest)request ;
    HttpServletResponse res = (HttpServletResponse)response ;
    HttpSession sess = req.getSession() ;

    boolean valid = true ;

    String uri = req.getRequestURI().substring( req.getContextPath().length() ) ;

    User user = null ;

    if( ( uri.length() < 2 ) ||
        ( uri.indexOf( "/images/" ) > -1 ) )
    {
      // do nothing...  valid is true, and we will show this page :-)
    }
    else if( sess == null )
    {
      valid = false ;
      sess = req.getSession( true ) ;
    }
    else
    {
      user = (User)sess.getAttribute( "User" ) ;
      valid = ( user != null ) ;
      if( valid )
      {
          valid = CHECK TO SEE IF THIS USER CAN ACCESS THIS PAGE
      }
    }
    if( !valid )
    {
        // Ok, the request is not valid, send them to the welcome page...
        log.info( "Denied access to " + uri ) ;
        String welcomePage = "/Welcome.do" ;
        String params = req.getQueryString() ;
        sess.setAttribute( "RedirectOnLogin", ( uri == null ? null : uri + ( params == null ? "" : "?" + params ) ) );
        res.sendRedirect( req.getContextPath() + welcomePage ) ;
    }
    else
    {
      if( uri.endsWith( ".do" ) ) // Stop people caching these pages...
      {
        // Set to expire far in the past.
        res.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT");

        // Set standard HTTP/1.1 no-cache headers.
        res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");

        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
        res.addHeader("Cache-Control", "post-check=0, pre-check=0");

        // Set standard HTTP/1.0 no-cache header.
        res.setHeader("Pragma", "no-cache");
      }
      chain.doFilter( request, response ) ;
    }
  }

  public void setFilterConfig( final FilterConfig filterConfig )
  {
    this.filterConfig = filterConfig ;
  }

  public void init( FilterConfig config )
  {
    this.filterConfig = config ;
  }

  public void destroy()
  {
    this.filterConfig = null ;
  }
}
0
 
TimYatesCommented:
You will need 2 levels of redirect.

1) If the user isn't logged in, where you store the URI they were trying to access, and send them to the login screen
2) if the user doesn't have the correct access rights, don't bother storing the URI, and send them to a "NO!" screen ;-)

Tim
0
 
petepalmerAuthor Commented:
oooh that's scary :)
0
 
TimYatesCommented:
I'd try it with just some logging first, and slowly add in your checks (using that code as a template) :-)

That way you can see what's happening at every step :-)

You can do things like check that POST methods come from your site too, which stops people saving HTML forms, hacking them, and posting them from their machine ;-)

One step at a time is the best way though ;-)

Good luck!!

Tim
0
 
petepalmerAuthor Commented:
Fingers crossed ;)
0
 
petepalmerAuthor Commented:
is filterConfig a requirement ? :)
0
 
petepalmerAuthor Commented:
Guess not, got it working without using it hehe....

Now to figure out what else it does....
0
 
petepalmerAuthor Commented:
How do I get objects out of "application" context from my funky new filter? :)

0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 8
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now