001 // $HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/portal/standard/security/control/LoginListener.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.portal.standard.security.control; 037 038 import java.io.IOException; 039 import java.io.Reader; 040 import java.io.StringReader; 041 import java.net.URL; 042 import java.net.URLEncoder; 043 import java.nio.charset.Charset; 044 045 import javax.servlet.http.HttpServletRequest; 046 import javax.servlet.http.HttpSession; 047 048 import org.deegree.enterprise.control.AbstractListener; 049 import org.deegree.enterprise.control.FormEvent; 050 import org.deegree.enterprise.control.RPCMethodCall; 051 import org.deegree.enterprise.control.RPCStruct; 052 import org.deegree.enterprise.control.RPCUtils; 053 import org.deegree.enterprise.control.RPCWebEvent; 054 import org.deegree.framework.log.ILogger; 055 import org.deegree.framework.log.LoggerFactory; 056 import org.deegree.framework.util.CharsetUtils; 057 import org.deegree.framework.util.NetWorker; 058 import org.deegree.framework.xml.NamespaceContext; 059 import org.deegree.framework.xml.XMLParsingException; 060 import org.deegree.framework.xml.XMLTools; 061 import org.deegree.i18n.Messages; 062 import org.deegree.ogcbase.BaseURL; 063 import org.deegree.ogcbase.CommonNamespaces; 064 import org.deegree.ogcwebservices.InvalidParameterValueException; 065 import org.deegree.ogcwebservices.OWSUtils; 066 import org.deegree.portal.Constants; 067 import org.deegree.portal.context.GeneralExtension; 068 import org.deegree.portal.context.ViewContext; 069 import org.w3c.dom.Document; 070 import org.xml.sax.SAXException; 071 072 /** 073 * Listener class for handling login to iGeoPortal standard edition 074 * 075 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> 076 * @author last edited by: $Author: mschneider $ 077 * 078 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 079 */ 080 public class LoginListener extends AbstractListener { 081 082 private static ILogger LOG = LoggerFactory.getLogger( LoginListener.class ); 083 084 private static final NamespaceContext nsContext = CommonNamespaces.getNamespaceContext(); 085 086 /** 087 * performs a login request. the passed event contains a RPC method call containing user name 088 * and password. 089 * 090 * @see org.deegree.enterprise.control.WebListener#actionPerformed(org.deegree.enterprise.control.FormEvent) 091 * 092 * @param event 093 */ 094 @Override 095 public void actionPerformed( FormEvent event ) { 096 097 RPCWebEvent re = (RPCWebEvent) event; 098 099 if ( !validateRequest( re ) ) { 100 gotoErrorPage( Messages.getMessage( "IGEO_STD_SEC_INVALID_LOGIN" ) ); 101 LOG.logDebug( Messages.getMessage( "IGEO_STD_SEC_INVALID_LOGIN" ) ); 102 return; 103 } 104 105 String[] result = null; 106 try { 107 result = performLogin( re ); 108 } catch ( InvalidParameterValueException ipve ) { 109 gotoErrorPage( ipve.toString() ); 110 LOG.logDebug( ipve.getMessage(), ipve ); 111 return; 112 } catch ( LoginFailureException lfe ) { 113 LOG.logDebug( lfe.getMessage(), lfe ); 114 try { 115 handleLoginFailure( lfe.getMessage() ); 116 } catch ( Exception e ) { 117 gotoErrorPage( e.toString() ); 118 LOG.logDebug( e.getMessage(), e ); 119 return; 120 } 121 return; 122 } catch ( Exception e ) { 123 gotoErrorPage( e.toString() ); 124 LOG.logDebug( e.getMessage(), e ); 125 return; 126 } 127 128 // write request parameter into session to reconstruct the search form 129 HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession( true ); 130 session.setAttribute( "SESSIONID", result[0] ); 131 getRequest().setAttribute( "SESSIONID", result[0] ); 132 getRequest().setAttribute( "USER", result[1] ); 133 } 134 135 /** 136 * handles the case if a login fails. extracts the message from the exception XML and pass it to 137 * the error page (error.jsp) 138 * 139 * @param messageXML 140 * @throws SAXException 141 * @throws XMLParsingException 142 * @throws IOException 143 */ 144 private void handleLoginFailure( String messageXML ) 145 throws SAXException, XMLParsingException, IOException { 146 Reader reader = new StringReader( messageXML ); 147 Document doc = XMLTools.parse( reader ); 148 String message = XMLTools.getRequiredNodeAsString( doc.getDocumentElement(), 149 "/ServiceExceptionReport/ServiceException", nsContext ); 150 gotoErrorPage( message ); 151 } 152 153 /** 154 * validates the passed event to be valid against the requirements of the listener (contains user 155 * name and password) 156 * 157 * @param event 158 * @return true if the request is valide 159 */ 160 private boolean validateRequest( RPCWebEvent event ) { 161 RPCMethodCall mc = event.getRPCMethodCall(); 162 if ( mc.getParameters().length == 0 ) { 163 return false; 164 } 165 RPCStruct struct = (RPCStruct) mc.getParameters()[0].getValue(); 166 if ( struct.getMember( "NAME" ) == null ) { 167 return false; 168 } 169 if ( struct.getMember( "PASSWORD" ) == null ) { 170 return false; 171 } 172 return true; 173 } 174 175 private String getAddress() { 176 HttpSession session = ( (HttpServletRequest) getRequest() ).getSession( true ); 177 ViewContext vc = (ViewContext) session.getAttribute( Constants.CURRENTMAPCONTEXT ); 178 GeneralExtension ge = vc.getGeneral().getExtension(); 179 BaseURL baseUrl = ge.getAuthentificationSettings().getAuthentificationURL(); 180 return NetWorker.url2String( baseUrl.getOnlineResource() ); 181 } 182 183 /** 184 * peforms a login by requesting a session ID from a WAAS like service (deegree SessionServlet). 185 * The returned session ID is assigned to a session at the WAAS like service to enable vice 186 * versa to identify the user through the ID. 187 * 188 * @param event 189 * @return a string array containing session id [0] and user name [1], if login was successful 190 * @throws InvalidParameterValueException 191 * @throws LoginFailureException 192 * if user/password is not known to the system. 193 * @throws IOException 194 */ 195 private String[] performLogin( RPCWebEvent event ) 196 throws InvalidParameterValueException, LoginFailureException, IOException { 197 RPCMethodCall mc = event.getRPCMethodCall(); 198 RPCStruct struct = (RPCStruct) mc.getParameters()[0].getValue(); 199 String name = RPCUtils.getRpcPropertyAsString( struct, "NAME" ); 200 String password = RPCUtils.getRpcPropertyAsString( struct, "PASSWORD" ); 201 if ( name == null || name.length() == 0 ) { 202 throw new InvalidParameterValueException( Messages.getMessage( "IGEO_STD_SEC_INVALID_USERNAME", name ) ); 203 } 204 if ( password == null || password.length() == 0 ) { 205 throw new InvalidParameterValueException( Messages.getMessage( "IGEO_STD_SEC_INVALID_PASSWORD" ) ); 206 } 207 208 // create request against WAS 209 StringBuffer sb = new StringBuffer( 500 ); 210 String address = OWSUtils.validateHTTPGetBaseURL( getAddress() ); 211 sb.append( address ); 212 sb.append( "SERVICE=WAS&VERSION=1.0.0&REQUEST=GetSession&" ); 213 sb.append( "AUTHMETHOD=urn:x-gdi-nrw:authnMethod:1.0:password&CREDENTIALS=" ); 214 sb.append( name ).append( ',' ).append( URLEncoder.encode( password, Charset.defaultCharset().displayName() ) ); 215 URL url = new URL( sb.toString() ); 216 217 // if the user is not known to the WAS an Exception is thrown at 218 // org.deegree.security.drm.SQLRegistry.getUserByName(SQLRegistry.java) 219 // "Lookup of user 'sadfas' failed! A user with this name does not exist." 220 221 // connect WAS to acquire a session ID 222 NetWorker nw = new NetWorker( CharsetUtils.getSystemCharset(), url ); 223 byte[] b = nw.getDataAsByteArr( 50 ); 224 String response = new String( b ); 225 226 // the byte array and the new String() may contain an xml exception message like this: 227 // <?xml version="1.0" encoding="ISO-8859-1"?> 228 // <ServiceExceptionReport> 229 // <ServiceException locator="-">Lookup of user 'sadfas' failed! A user with this name does 230 // not exist.</ServiceException> 231 // </ServiceExceptionReport> 232 233 if ( response.contains( "ServiceExceptionReport" ) ) { 234 throw new LoginFailureException( response ); 235 } 236 237 // return session id and user name if login was successful 238 String[] res = new String[2]; 239 res[0] = response; 240 res[1] = name; 241 return res; 242 } 243 244 }