SecurityService.java
- /*
- * Copyright (c) 2002-2022, City of Paris
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice
- * and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice
- * and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * License 1.0
- */
- package fr.paris.lutece.portal.service.security;
- import fr.paris.lutece.portal.business.event.LuteceUserEvent;
- import fr.paris.lutece.portal.service.datastore.DatastoreService;
- import fr.paris.lutece.portal.service.event.LuteceUserEventManager;
- import fr.paris.lutece.portal.service.init.LuteceInitException;
- import fr.paris.lutece.portal.service.util.AppLogService;
- import fr.paris.lutece.portal.service.util.AppPropertiesService;
- import fr.paris.lutece.util.url.UrlItem;
- import java.security.Principal;
- import java.util.Collection;
- import java.util.Enumeration;
- import java.util.List;
- import javax.security.auth.login.LoginException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpSession;
- /**
- * This class provides a security service to register and check user authentication
- */
- public final class SecurityService
- {
- /**
- * Session attribute that stores the LuteceUser object attached to the session
- */
- private static final String ATTRIBUTE_LUTECE_USER = "lutece_user";
- private static final String PROPERTY_AUTHENTICATION_CLASS = "mylutece.authentication.class";
- private static final String PROPERTY_AUTHENTICATION_ENABLE = "mylutece.authentication.enable";
- private static final String PROPERTY_PORTAL_AUTHENTICATION_REQUIRED = "mylutece.portal.authentication.required";
- private static final String URL_INTERROGATIVE = "?";
- private static final String URL_AMPERSAND = "&";
- private static final String URL_EQUAL = "=";
- private static final String CONSTANT_ACTION_LOGIN_USER = "user.loginUser";
- private static final String CONSTANT_ACTION_LOGOUT_USER = "user.logoutUser";
- private static final String CONSTANT_FO = "FO";
- private static SecurityService _singleton = new SecurityService( );
- private static LuteceAuthentication _authenticationService;
- private static boolean _bEnable;
- /**
- * Private constructor
- */
- private SecurityService( )
- {
- }
- /**
- * Initialize service
- *
- * @throws LuteceInitException
- * if an error occurs
- */
- public static synchronized void init( ) throws LuteceInitException
- {
- _bEnable = false;
- String strEnable = AppPropertiesService.getProperty( PROPERTY_AUTHENTICATION_ENABLE, "false" );
- if ( strEnable.equalsIgnoreCase( "true" ) )
- {
- _authenticationService = getPortalAuthentication( );
- if ( _authenticationService != null )
- {
- _bEnable = true;
- }
- }
- else
- {
- // in case authentication is disabled after having been enabled
- _authenticationService = null;
- }
- }
- /**
- * Get the unique instance of the Security Service
- *
- * @return The instance
- */
- public static SecurityService getInstance( )
- {
- return _singleton;
- }
- /**
- * Returns the authentication's activation : enable or disable
- *
- * @return true if the authentication is active, false otherwise
- */
- public static boolean isAuthenticationEnable( )
- {
- return _bEnable;
- }
- /**
- * Gets the LuteceUser attached to the current Http session
- *
- * @param request
- * The Http request
- * @return A LuteceUser object if found
- * @throws UserNotSignedException
- * If there is no current user
- */
- public LuteceUser getRemoteUser( HttpServletRequest request ) throws UserNotSignedException
- {
- LuteceUser user = getRegisteredUser( request );
- if ( user == null )
- {
- // User is not registered by Lutece, but it may be authenticated by another
- // system
- if ( _authenticationService.isExternalAuthentication( ) || _authenticationService.isMultiAuthenticationSupported( ) )
- {
- user = _authenticationService.getHttpAuthenticatedUser( request );
- if ( ( user == null ) && isPortalAuthenticationRequired( ) )
- {
- throw new UserNotSignedException( );
- }
- registerUser( request, user );
- }
- else
- {
- throw new UserNotSignedException( );
- }
- }
- return user;
- }
- /**
- * Returns the user's principal
- *
- * @param request
- * The HTTP request
- * @return The user's principal
- * @throws UserNotSignedException
- * The UserNotSignedException
- */
- public Principal getUserPrincipal( HttpServletRequest request ) throws UserNotSignedException
- {
- return getRemoteUser( request );
- }
- /**
- * Checks if the user is associated to a given role
- *
- * @param request
- * The Http request
- * @param strRole
- * The Role name
- * @return Returns true if the user is associated to the given role
- */
- public boolean isUserInRole( HttpServletRequest request, String strRole )
- {
- LuteceUser user;
- if ( !isAuthenticationEnable( ) )
- {
- return true;
- }
- try
- {
- user = getRemoteUser( request );
- }
- catch( UserNotSignedException e )
- {
- return false;
- }
- return _authenticationService.isUserInRole( user, request, strRole );
- }
- /**
- * Checks if the user is associated to a at least a role
- *
- * @param request
- * The Http request
- * @param listRoles
- * The Role list
- * @return Returns true if the user is associated to any role
- */
- public boolean isUserInAnyRole( HttpServletRequest request, List<String> listRoles )
- {
- boolean bAutorized = false;
- for ( String strRole : listRoles )
- {
- if ( isUserInRole( request, strRole ) )
- {
- bAutorized = true;
- break;
- }
- }
- return bAutorized;
- }
- /**
- * get all roles for this user : - user's roles - user's groups roles
- *
- * @param user
- * The user
- * @return Array of roles
- */
- public String [ ] getRolesByUser( LuteceUser user )
- {
- return _authenticationService.getRolesByUser( user );
- }
- /**
- * Checks user's login with the Authentication service.
- *
- * @param request
- * The Http request
- * @param strUserName
- * The user's login
- * @param strPassword
- * The user's password
- * @throws LoginException
- * The LoginException
- * @throws LoginRedirectException
- * if redirect exception
- */
- public void loginUser( HttpServletRequest request, final String strUserName, final String strPassword ) throws LoginException, LoginRedirectException
- {
- LuteceUser user = _authenticationService.login( strUserName, strPassword, request );
- _authenticationService.updateDateLastLogin( user, request );
- if ( _authenticationService.findResetPassword( request, strUserName ) )
- {
- String redirect = _authenticationService.getResetPasswordPageUrl( request );
- registerUser( request, user );
- AccessLogService.getInstance( ).info( AccessLoggerConstants.EVENT_TYPE_CONNECT, CONSTANT_ACTION_LOGIN_USER, user, null, CONSTANT_FO );
- throw new LoginRedirectException( redirect );
- }
- registerUser( request, user );
- AccessLogService.getInstance( ).info( AccessLoggerConstants.EVENT_TYPE_CONNECT, CONSTANT_ACTION_LOGIN_USER, user, null, CONSTANT_FO );
- }
- /**
- * Logout the user
- *
- * @param request
- * The HTTP request
- */
- public void logoutUser( HttpServletRequest request )
- {
- LuteceUser user;
- try
- {
- user = getRemoteUser( request );
- }
- catch( UserNotSignedException e )
- {
- return;
- }
- _authenticationService.logout( user );
- HttpSession session = request.getSession( false );
- if(session!=null)
- {
- session.invalidate();
- }
- LuteceUserEventManager.getInstance().notifyListeners( new LuteceUserEvent( user,LuteceUserEvent.EventType.LOGOUT ) );
- AccessLogService.getInstance( ).info( AccessLoggerConstants.EVENT_TYPE_DISCONNECT, CONSTANT_ACTION_LOGOUT_USER, user, null, CONSTANT_FO );
- }
- /**
- * Retrieves the portal authentication service configured in the config.properties
- *
- * @return A PortalAuthentication object
- * @throws LuteceInitException
- * If an error occurred
- */
- private static LuteceAuthentication getPortalAuthentication( ) throws LuteceInitException
- {
- String strAuthenticationClass = AppPropertiesService.getProperty( PROPERTY_AUTHENTICATION_CLASS );
- LuteceAuthentication authentication = null;
- if ( ( strAuthenticationClass != null ) && !strAuthenticationClass.equals( "" ) )
- {
- try
- {
- authentication = (LuteceAuthentication) Class.forName( strAuthenticationClass ).newInstance( );
- AppLogService.info( "Authentication service loaded : {}", authentication.getAuthServiceName( ) );
- }
- catch( InstantiationException | IllegalAccessException | ClassNotFoundException e )
- {
- throw new LuteceInitException( "Error instantiating Authentication Class", e );
- }
- }
- return authentication;
- }
- /**
- * Register the user in the Http session
- *
- * @param request
- * The Http request
- * @param user
- * The current user
- */
- public void registerUser( HttpServletRequest request, LuteceUser user )
- {
- HttpSession session = request.getSession( true );
- session.setAttribute( ATTRIBUTE_LUTECE_USER, user );
-
- if ( user != null )
- {
- LuteceUserEventManager.getInstance().notifyListeners( new LuteceUserEvent( user, LuteceUserEvent.EventType.LOGIN_SUCCESSFUL ) );
- }
- }
- /**
- * Unregister the user in the Http session
- *
- * @param request
- * The Http request
- */
- public void unregisterUser( HttpServletRequest request )
- {
- HttpSession session = request.getSession( true );
- LuteceUser user = (LuteceUser)session.getAttribute( ATTRIBUTE_LUTECE_USER );
-
- if ( user != null )
- {
- session.removeAttribute( ATTRIBUTE_LUTECE_USER );
- }
- }
- /**
- * Gets the Lutece user registered in the Http session
- *
- * @param request
- * The HTTP request
- * @return The User registered or null if the user has not been registered
- */
- public LuteceUser getRegisteredUser( HttpServletRequest request )
- {
- HttpSession session = ( request != null ) ? request.getSession( false ) : null;
- if ( session != null )
- {
- return (LuteceUser) session.getAttribute( ATTRIBUTE_LUTECE_USER );
- }
- return null;
- }
- /**
- * Returns the authentication type : External or Lutece portal based
- *
- * @return true if the user is already authenticated or false if it needs to login.
- */
- public boolean isExternalAuthentication( )
- {
- return _authenticationService.isExternalAuthentication( );
- }
- /**
- * Returns the Login page URL of the Authentication Service
- *
- * @return The URL
- */
- public String getLoginPageUrl( )
- {
- return _authenticationService.getLoginPageUrl( );
- }
- /**
- * Returns the DoLogin URL of the Authentication Service
- *
- * @return The URL
- */
- public String getDoLoginUrl( )
- {
- return _authenticationService.getDoLoginUrl( );
- }
- /**
- * Returns the DoLogout URL of the Authentication Service
- *
- * @return The URL
- */
- public String getDoLogoutUrl( )
- {
- return _authenticationService.getDoLogoutUrl( );
- }
- /**
- * Returns the new account page URL of the Authentication Service
- *
- * @return The URL
- */
- public String getNewAccountPageUrl( )
- {
- return _authenticationService.getNewAccountPageUrl( );
- }
- /**
- * Returns the view account page URL of the Authentication Service
- *
- * @return The URL
- */
- public String getViewAccountPageUrl( )
- {
- return _authenticationService.getViewAccountPageUrl( );
- }
- /**
- * Returns the lost password URL of the Authentication Service
- *
- * @return The URL
- */
- public String getLostPasswordPageUrl( )
- {
- return _authenticationService.getLostPasswordPageUrl( );
- }
- // Added in v1.3
- /**
- * Returns the access denied template
- *
- * @return The template
- */
- public String getAccessDeniedTemplate( )
- {
- return _authenticationService.getAccessDeniedTemplate( );
- }
- /**
- * Returns the access controled template
- *
- * @return The template
- */
- public String getAccessControledTemplate( )
- {
- return _authenticationService.getAccessControledTemplate( );
- }
- /**
- * Returns whether or not the portal needs authentication
- *
- * @return true if the access needs authentication, otherwise
- * @since 1.3.1
- */
- public boolean isPortalAuthenticationRequired( )
- {
- String strAuthenticationRequired = DatastoreService.getDataValue( PROPERTY_PORTAL_AUTHENTICATION_REQUIRED, "false" );
- return strAuthenticationRequired.equals( "true" );
- }
- /**
- * Checks user's login with the Authentication service. Used during remote authentication validation We don't have to put user informations in session,
- * since it is only used in external applications
- *
- * @param request
- * the request
- * @param strUserName
- * The user's login
- * @param strPassword
- * The user's password
- * @return user's informations
- * @throws LoginException
- * The LoginException
- * @throws LoginRedirectException
- * The redirect exception
- */
- public LuteceUser remoteLoginUser( final HttpServletRequest request, final String strUserName, final String strPassword )
- throws LoginException, LoginRedirectException
- {
- return _authenticationService.login( strUserName, strPassword, request );
- }
- /**
- * Return true if the requested url is equal to LoginUrl
- *
- * @param request
- * The Http servlet request
- * @return True if the requested url is equal to LoginUrl, false else.
- */
- public boolean isLoginUrl( HttpServletRequest request )
- {
- if ( ( getLoginPageUrl( ) == null ) || ( request == null ) )
- {
- return false;
- }
- String strRequestUrl = request.getRequestURI( );
- UrlItem url = new UrlItem( strRequestUrl );
- for ( String strParamValueLoginPageUrl : getLoginPageUrl( ).substring( getLoginPageUrl( ).indexOf( URL_INTERROGATIVE ) + 1 ).split( URL_AMPERSAND ) )
- {
- String [ ] arrayParamValueLoginPageUrl = strParamValueLoginPageUrl.split( URL_EQUAL );
- Enumeration<String> enumParams = request.getParameterNames( );
- while ( enumParams.hasMoreElements( ) )
- {
- String strRequestParameter = enumParams.nextElement( );
- if ( arrayParamValueLoginPageUrl [0].equals( strRequestParameter )
- && arrayParamValueLoginPageUrl [1].equals( request.getParameter( strRequestParameter ) ) )
- {
- url.addParameter( strRequestParameter, request.getParameter( strRequestParameter ) );
- }
- }
- }
- return url.getUrl( ).endsWith( getLoginPageUrl( ) ) && !getLoginPageUrl( ).equals( "" );
- }
- /**
- * Tells whether or not the authentication service can provide a list of all its users
- *
- * @return true if the service can return a users list
- */
- boolean isUsersListAvailable( )
- {
- return _authenticationService.isUsersListAvailable( );
- }
- /**
- * Returns all users managed by the authentication service if this feature is available.
- *
- * @return A collection of Lutece users or null if the service doesn't provide a users list
- */
- public Collection<LuteceUser> getUsers( )
- {
- return _authenticationService.getUsers( );
- }
- /**
- * Returns user managed by the authentication service if this feature is available.
- *
- * @param strUserLogin
- * the user login
- * @return A Lutece user or null if the service doesn't provide LuteceUser
- */
- public LuteceUser getUser( String strUserLogin )
- {
- return _authenticationService.getUser( strUserLogin );
- }
- /**
- * <b>true</b> when the service provides multi authentication support
- *
- * @return <code>true</code> if multi authentication is supported, <code>false</code> otherwise.
- */
- public boolean isMultiAuthenticationSupported( )
- {
- return _authenticationService.isMultiAuthenticationSupported( );
- }
- /**
- * Gets the actual authentication implementation
- *
- * @return {@link LuteceAuthentication} implementation
- */
- public LuteceAuthentication getAuthenticationService( )
- {
- return _authenticationService;
- }
- }