// $Header: /home/deegree/jail/deegreerepository/deegree/src/org/deegree/portal/standard/security/control/LoginListener.java,v 1.11 2006/11/30 13:50:02 mays Exp $ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2006 by: University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de This library 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.1 of the License, or (at your option) any later version. This library 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 Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53115 Bonn Germany E-Mail: poth@lat-lon.de Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: klaus.greve@uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.portal.standard.security.control; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.net.URL; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.deegree.enterprise.control.AbstractListener; import org.deegree.enterprise.control.FormEvent; import org.deegree.enterprise.control.RPCMethodCall; import org.deegree.enterprise.control.RPCStruct; import org.deegree.enterprise.control.RPCUtils; import org.deegree.enterprise.control.RPCWebEvent; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.CharsetUtils; import org.deegree.framework.util.NetWorker; import org.deegree.framework.xml.NamespaceContext; import org.deegree.framework.xml.XMLParsingException; import org.deegree.framework.xml.XMLTools; import org.deegree.ogcbase.BaseURL; import org.deegree.ogcbase.CommonNamespaces; import org.deegree.ogcwebservices.InvalidParameterValueException; import org.deegree.ogcwebservices.OWSUtils; import org.deegree.portal.Constants; import org.deegree.portal.context.GeneralExtension; import org.deegree.portal.context.ViewContext; import org.w3c.dom.Document; import org.xml.sax.SAXException; /** * Listener class for handling login to iGeoPortal standard edition * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> * @author last edited by: $Author: mays $ * * @version $Revision: 1.11 $, $Date: 2006/11/30 13:50:02 $ */ public class LoginListener extends AbstractListener { private static ILogger LOG = LoggerFactory.getLogger( LoginListener.class ); private static final NamespaceContext nsContext = CommonNamespaces.getNamespaceContext(); /** * performs a login request. the passed event contains a RPC method call containing user name * and password. * @see org.deegree.enterprise.control.WebListener#actionPerformed(org.deegree.enterprise.control.FormEvent) * * @param event */ @Override public void actionPerformed( FormEvent event ) { RPCWebEvent re = (RPCWebEvent) event; if ( !validateRequest( re ) ) { String s = "Invalid content for login. Please validate if you have NAME and PASSWORD"; gotoErrorPage( s ); LOG.logDebug( s ); return; } String[] result = null; try { result = performLogin( re ); } catch ( InvalidParameterValueException ipve ) { gotoErrorPage( ipve.toString() ); LOG.logDebug( ipve.getMessage(), ipve ); return; } catch ( LoginFailureException lfe ) { LOG.logDebug( lfe.getMessage(), lfe ); try { handleLoginFailure( lfe.getMessage() ); } catch ( Exception e ) { gotoErrorPage( e.toString() ); return; } return; } catch ( Exception e ) { gotoErrorPage( e.toString() ); LOG.logDebug( e.getMessage(), e ); return; } // write request parameter into session to reconstruct the search form HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession( true ); session.setAttribute( "SESSIONID", result[0] ); getRequest().setAttribute( "SESSIONID", result[0] ); getRequest().setAttribute( "USER", result[1] ); } /** * handles the case if a login fails. extracts the message from the exception XML and pass it to * the error page (error.jsp) * * @param messageXML * @throws SAXException * @throws XMLParsingException * @throws IOException */ private void handleLoginFailure( String messageXML ) throws SAXException, XMLParsingException, IOException { Reader reader = new StringReader( messageXML ); Document doc = XMLTools.parse( reader ); String message = XMLTools.getRequiredNodeAsString( doc.getDocumentElement(), "/ServiceExceptionReport/ServiceException", nsContext ); gotoErrorPage( message ); } /** * validates the passed event to be valid agaist the requirements of the listener (contains user * name and password) * * @param event * @return true if the request is valide */ private boolean validateRequest( RPCWebEvent event ) { RPCMethodCall mc = event.getRPCMethodCall(); if ( mc.getParameters().length == 0 ) { return false; } RPCStruct struct = (RPCStruct) mc.getParameters()[0].getValue(); if ( struct.getMember( "NAME" ) == null ) { return false; } if ( struct.getMember( "PASSWORD" ) == null ) { return false; } return true; } private String getAddress() { HttpSession session = ( (HttpServletRequest) getRequest() ).getSession( true ); ViewContext vc = (ViewContext) session.getAttribute( Constants.CURRENTMAPCONTEXT ); GeneralExtension ge = vc.getGeneral().getExtension(); BaseURL baseUrl = ge.getAuthentificationSettings().getAuthentificationURL(); return NetWorker.url2String( baseUrl.getOnlineResource() ); } /** * peforms a login by requesting a session ID from a WAAS like service (deegre SessionServlet). * The returned session ID is assigned to a session at the WAAS like service to enable vice * versa to identify the user through the ID. * * @param event * @return a string array containing session id [0] and user name [1], if login was successful * @throws InvalidParameterValueException * @throws LoginFailureException if user/passwd is not known to the system. * @throws IOException */ private String[] performLogin( RPCWebEvent event ) throws InvalidParameterValueException, LoginFailureException, IOException { RPCMethodCall mc = event.getRPCMethodCall(); RPCStruct struct = (RPCStruct) mc.getParameters()[0].getValue(); String name = RPCUtils.getRpcPropertyAsString( struct, "NAME" ); String password = RPCUtils.getRpcPropertyAsString( struct, "PASSWORD" ); if ( name == null || name.length() == 0 ) { throw new InvalidParameterValueException( "Invalid user name: " + name ); } if ( password == null || password.length() == 0 ) { throw new InvalidParameterValueException( "Invalid user password" ); } // create request against WAS StringBuffer sb = new StringBuffer( 500 ); String address = OWSUtils.validateHTTPGetBaseURL( getAddress() ); sb.append( address ); sb.append( "SERVICE=WAS&VERSION=1.0.0&REQUEST=GetSession&" ); sb.append( "AUTHMETHOD=urn:x-gdi-nrw:authnMethod:1.0:password&CREDENTIALS=" ); sb.append( name ).append( ',' ).append( password ); URL url = new URL( sb.toString() ); // if the user is not known to the WAS an Exception is thrown at // org.deegree.security.drm.SQLRegistry.getUserByName(SQLRegistry.java:276) // "ERROR: Lookup of user 'sadfas' failed! A user with this name does not exist." // this Exception message gets transformed at // org.deegree.ogcwebservices.wass.was.WAService.doService(WAService.java:188) // to something like "ERROR: WAService: There was an internal error in the security system." // connect WAS to aquire a seesion ID NetWorker nw = new NetWorker( CharsetUtils.getSystemCharset(), url ); byte[] b = nw.getDataAsByteArr( 50 ); String response = new String( b ); // the bytearray and the new String() may contain an xml exception message: // <?xml version="1.0" encoding="ISO-8859-1"?> // <ServiceExceptionReport> // <ServiceException locator="-">WAService: There was an internal error in the security system.</ServiceException> // </ServiceExceptionReport> if ( response.contains( "ServiceExceptionReport" ) ) { throw new LoginFailureException( response ); } // return session id and user name if login was successful String[] res = new String[2]; res[0] = response; res[1] = name; return res; } } /* ******************************************************************** Changes to this class. What the people have been up to: $Log: LoginListener.java,v $ Revision 1.11 2006/11/30 13:50:02 mays change handleLoginFailure() according to changes in performLogin() Revision 1.10 2006/11/30 12:22:29 mays change handling of login failure in performLogin(); clean up javadocs and format code Revision 1.7 2006/08/29 08:16:47 taddei forcing base url to end with ? (attempt at bug fix) Revision 1.6 2006/08/09 14:01:33 poth bug fix - support for GDINRW Access Control 1.0 / references to deprecated class Debug removed / Logger added Revision 1.5 2006/07/13 08:10:56 poth file header added / references to Debug.XXXX removed Revision 1.4 2006/07/12 14:46:15 poth comment footer added ********************************************************************** */