AuthFilter.java :  » Web-Framework » argun » biz » hammurapi » web » security » Java Open Source

Java Open Source » Web Framework » argun 
argun » biz » hammurapi » web » security » AuthFilter.java
/*
 * argun 1.0
 * Web 2.0 delivery framework 
 * Copyright (C) 2007  Hammurapi Group
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * URL: http://www.hammurapi.biz
 * e-Mail: support@hammurapi.biz
 */

package biz.hammurapi.web.security;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

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.codec.binary.Base64;

import biz.hammurapi.authorization.AuthorizationProvider;
import biz.hammurapi.config.Context;
import biz.hammurapi.web.HammurapiWebException;
import biz.hammurapi.web.menu.MenuFilter;
import biz.hammurapi.web.security.sql.ApplicationPermission;
import biz.hammurapi.web.security.sql.SecurityEngine;

/**
 * This class handles authentication - it makes sure that each request is authenticated 
 * @author  Pavel Vlasov
 * @version $Revision: 1.1 $
 */
public class AuthFilter implements Filter {
  
  public static final String LOGIN_TARGET = "login-target";
  public static final String LOGIN_URL_ATTRIBUTE = AuthFilter.class.getName()+":login-url";
  public static final String MAX_LOGIN_ATTEMPTS = "max-login-attempts";
  public static final String AUTHORIZATION_PROVIDER = AuthorizationProvider.class.getName();
  public static final String USER = User.class.getName();
  public static final String REMAINING_LOGIN_ATTEMPTS = "remaining-login-attempts";
  private static final String DEBUG = "debug";
  private String loginUrl;
  private String realm;
  private int maxAttempts = 6;
  private String unauthenticatedPrincipal;
  private boolean debug;
  private Integer maxAttemptsInteger = new Integer(maxAttempts);
  private FilterConfig filterConfig;
    
    /**
     * Init method for this filter
     *
     */
    public void init(final FilterConfig filterConfig) throws ServletException {   
      filterConfig.getServletContext().log("Initializing authentication filter");
    loginUrl=filterConfig.getInitParameter("login-url");
    if (loginUrl!=null) {
        filterConfig.getServletContext().log("loginUrl="+loginUrl);
    }
    
    realm=filterConfig.getInitParameter("realm");
    if (realm!=null) {
        filterConfig.getServletContext().log("realm="+realm);
    }
    
    String maStr = filterConfig.getInitParameter("max-attempts");
    if (maStr!=null) {
      maxAttempts = Integer.parseInt(maStr);
        maxAttemptsInteger = new Integer(maxAttempts);
    }
    
    unauthenticatedPrincipal = filterConfig.getInitParameter("unauthenticated-principal");
    if (unauthenticatedPrincipal!=null) {
      filterConfig.getServletContext().log("unauthenticated principal="+unauthenticatedPrincipal);
    }
    
    debug = "yes".equals(filterConfig.getInitParameter(DEBUG));
    
      filterConfig.getServletContext().log("Max login attempts="+maxAttempts);
    filterConfig.getServletContext().setAttribute("filter/"+filterConfig.getFilterName(), this);
      this.filterConfig = filterConfig;
    }
    
    /**
     * @return Name of unauthenticated principal (guest user) for this application.
     */
    public String getUnauthenticatedPrincipal() {
    return unauthenticatedPrincipal;
  }
    
    /**
     * Checks user in session. If user is present then authorization provider is injected into request.
     * If there is no credentials then Guest credentials are used if such user exists and is not blocked.
     * If Guest user doesn't exists then control is passed to login url. If login URL is null then basic 
     * authentication is used.
     * @param request The servlet request we are processing
     * @param result The servlet response we are creating
     * @param chain The filter chain we are processing
     *
     * @exception IOException if an input/output error occurs
     * @exception ServletException if a servlet error occurs
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
      if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpSession session = httpRequest.getSession();
      session.setAttribute(MAX_LOGIN_ATTEMPTS, maxAttemptsInteger);
      if (loginUrl!=null) {
        String ctxPath = httpRequest.getContextPath();
        if (ctxPath.endsWith("/")) {
          ctxPath = ctxPath.substring(0, ctxPath.length()-1);
        }
        request.setAttribute(LOGIN_URL_ATTRIBUTE, ctxPath+loginUrl);
      }
        
        try {
          // Get authorization provider.
          if (session.getAttribute(AUTHORIZATION_PROVIDER) != null) {
            if (debug || "yes".equals(request.getParameter("reloadUser"))) {
              reload(httpRequest);
            }
            chain.doFilter(request, response);
          } else {
              // Get guest user
            if (authorize(httpRequest, null, null)) {
              chain.doFilter(request, response);
            } else {
              if (loginUrl==null) {
                  // If login page is null then do basic authentication
                  String auth = httpRequest.getHeader("Authorization");
                  if (auth == null) {
                      httpResponse.setHeader("WWW-Authenticate", "BASIC realm=\""+realm+"\""); 
                         httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);                   
                  } else if (auth.toUpperCase().startsWith("BASIC ")) {
                    String decoded = new String(Base64.decodeBase64(auth.substring(6).getBytes()));
                    int idx = decoded.indexOf(":");
                    if (idx != -1 && authorize(httpRequest, decoded.substring(0, idx), decoded.substring(idx+1))) {
                      session.removeAttribute(REMAINING_LOGIN_ATTEMPTS);
                      chain.doFilter(request, response);
                    } else {                      
                      Integer attempts = (Integer) session.getAttribute(REMAINING_LOGIN_ATTEMPTS);
                      if (attempts==null) {
                        session.setAttribute(REMAINING_LOGIN_ATTEMPTS, maxAttemptsInteger);
                      } else {
                        if (attempts.intValue()<=0) {
                          httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Too many failed login attempts");
                          return;
                        }
                        session.setAttribute(REMAINING_LOGIN_ATTEMPTS, new Integer(attempts.intValue()-1));
                      }
                        httpResponse.setHeader("WWW-Authenticate", "BASIC realm=\""+realm+"\""); 
                           httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
                    }
                  } else {
                    httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "");          
                  }                            
              } else {
//                System.out.println(httpRequest.getRequestURI());
                if (loginUrl.equals(httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()))) {
                  chain.doFilter(request, response);
                } else {
                  Integer attempts = (Integer) session.getAttribute(REMAINING_LOGIN_ATTEMPTS);
                  if (attempts==null) {
                    session.setAttribute(REMAINING_LOGIN_ATTEMPTS, maxAttemptsInteger);
                  } else {
                    if (attempts.intValue()<=0) {
                      httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Too many failed login attempts");
                      return;
                    }
                    session.setAttribute(REMAINING_LOGIN_ATTEMPTS, new Integer(attempts.intValue()-1));
                  }                
                    // If guest user is null - redirect to login page
                  String queryString = httpRequest.getQueryString();
                  if (queryString==null) {
                    session.setAttribute(LOGIN_TARGET, httpRequest.getRequestURL().toString());
                  } else {
                    session.setAttribute(LOGIN_TARGET, httpRequest.getRequestURL().append("?").append(queryString).toString());                
                  }
                  httpResponse.sendRedirect(httpRequest.getContextPath()+loginUrl);
                      PrintWriter out = response.getWriter();
                      out.write("<HTML><HEAD></HEAD><BODY>");
                      out.write("Redirecting to <a href=\""+httpRequest.getContextPath()+loginUrl+"\">login page</a>");
                      out.write("</BODY></HTML>");
                }
              }            
            }
          }                                
          } catch (HammurapiWebException e) {
            throw new ServletException("Authorization failed: "+e, e);
          }
      } else {
        chain.doFilter(request, response);
      }
    }

  public void destroy() {
    // Nothing to do here.
  }
  
  private Map classPermissions = new HashMap();

  /**
   * Constructs authorization provider for user. Injects user into session.
   * @param request
   * @param loginName
   * @param password
   * @return
   * @throws SQLException
   */
  private boolean authorize(HttpServletRequest request, String loginName, String password) throws HammurapiWebException {
    try {
      SecurityEngine engine = (SecurityEngine) ((Context) request.getAttribute("global")).get("db/SecurityEngine");
      if (loginName==null && getUnauthenticatedPrincipal()==null) {
        return false;
      }
      
      User user = (User) engine.getApplicationUser(loginName==null ? getUnauthenticatedPrincipal() : loginName, User.class);
      
      if (user==null || user.getIsBlocked()) {
        return false;
      }
    
       if (loginName!=null && (password==null || !ApplicationUserActions.hashPassword(password).equals(user.getUserPassword()))) {  
         return false;
       }
         
      Collection permissions = engine.getApplicationPermission(new ArrayList());
      Iterator it = permissions.iterator();
      while (it.hasNext()) {
        ApplicationPermission ap = (ApplicationPermission) it.next();
        if (!Boolean.TRUE.equals(user.hasPermission(ap.getClassName(), ap.getActionName()))) {
          it.remove();
        }
      }    
      
      HttpSession session = request.getSession();
      session.setAttribute(USER, user);
      session.setAttribute(AUTHORIZATION_PROVIDER, new UserAuthorizationProvider(user, permissions, classPermissions));
      return getMenuFilter().buildMenu(request);
    } catch (SQLException e) {
      throw new HammurapiWebException("Authorization failed: "+e, e);
    }
  }

  private MenuFilter getMenuFilter() {
    return (MenuFilter) filterConfig.getServletContext().getAttribute("filter/MenuFilter");
  }
        
  /**
   * Reloads user and menu at each request. Useful during develpment.
   * @param request
   * @return
   * @throws SQLException
   */
  private boolean reload(HttpServletRequest request) throws HammurapiWebException {
    try {
      SecurityEngine engine = (SecurityEngine) ((Context) request.getAttribute("global")).get("db/SecurityEngine");
      HttpSession session = request.getSession();      
      User user = (User) session.getAttribute(USER);            
      user = (User) engine.getApplicationUser(user.getLoginName(), User.class);
      
      Collection permissions = engine.getApplicationPermission(new ArrayList());
      Iterator it = permissions.iterator();
      while (it.hasNext()) {
        ApplicationPermission ap = (ApplicationPermission) it.next();
        if (!Boolean.TRUE.equals(user.hasPermission(ap.getClassName(), ap.getActionName()))) {
          it.remove();
        }
      }    
      
      session.setAttribute(USER, user);
      session.setAttribute(AUTHORIZATION_PROVIDER, new UserAuthorizationProvider(user, permissions, classPermissions));
      return getMenuFilter().buildMenu(request);
    } catch (SQLException e) {
      throw new HammurapiWebException("Authorization failed: "+e, e);
    }
  }
}
    




















java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.