PasswordUtil.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.util.password;
- import fr.paris.lutece.portal.service.admin.AdminUserService;
- import fr.paris.lutece.portal.service.util.AppPropertiesService;
- import fr.paris.lutece.util.date.DateUtil;
- import java.security.SecureRandom;
- import java.sql.Timestamp;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Random;
- /**
- * Utility class used to generate random passwords
- */
- public final class PasswordUtil
- {
- public static final String PROPERTY_PASSWORD_SIZE = "randomPassword.size";
- public static final int CONSTANT_DEFAULT_RANDOM_PASSWORD_SIZE = 16;
- private static final int CONSTANT_NUMBER_LETTERS = 26;
- private static final int CONSTANT_NUMBER_NUMBERS_BASE10 = 10;
- private static final int CONSTANT_ASCII_CODE_A_UPPERCASE = 65;
- private static final int CONSTANT_ASCII_CODE_A_LOWERCASE = 97;
- private static final int CONSTANT_ASCII_CODE_ZERO = 48;
- private static final char [ ] CONSTANT_SPECIAL_CHARACTERS = {
- '!', ',', ':', '?', '$', '-', '@', '}', '{', '(', ')', '*', '+', '=', '[', ']', '%', '.',
- };
- private static final String CONSTANT_PASSWORD_BEGIN_REGEX = "^";
- private static final String CONSTANT_PASSWORD_REGEX_NUM = "(?=.*[0-9])";
- private static final String CONSTANT_PASSWORD_REGEX_SPECIAL = "(?=.*[^a-zA-Z0-9])";
- private static final String CONSTANT_PASSWORD_REGEX_UPPER_LOWER = "(?=.*[a-z])(?=.*[A-Z])";
- private static final String CONSTANT_PASSWORD_END_REGEX = "(.*)$";
- private static final String PARAMETER_PASSWORD_MINIMUM_LENGTH = "password_minimum_length";
- /** Private Constructor */
- private PasswordUtil( )
- {
- }
- /**
- * Generate a new random password
- *
- * @return the new password
- */
- public static String makePassword( )
- {
- // reinitialize password
- int nPasswordSize = AppPropertiesService.getPropertyInt( PROPERTY_PASSWORD_SIZE, CONSTANT_DEFAULT_RANDOM_PASSWORD_SIZE );
- int nMinPasswordSize = AdminUserService.getIntegerSecurityParameter( PARAMETER_PASSWORD_MINIMUM_LENGTH );
- if ( nMinPasswordSize > nPasswordSize )
- {
- nPasswordSize = nMinPasswordSize;
- }
- return makePassword( nPasswordSize, true, true, true );
- }
- /**
- * Generate a new random password
- *
- * @param nPasswordSize
- * the password size
- * @param bUpperAndLowerCase
- * true if the password must contain upper and lower case
- * @param bNumbers
- * if the password must contain numbers
- * @param bSpecialCaracters
- * if the password must contain special characters
- *
- * @return the new password
- */
- public static String makePassword( int nPasswordSize, boolean bUpperAndLowerCase, boolean bNumbers, boolean bSpecialCaracters )
- {
- // reinitialize password
- Random r = new SecureRandom( );
- ArrayList<Character> listCharacters = new ArrayList<>( nPasswordSize );
- // No of Big letters
- int nNumCapitalLetters = bUpperAndLowerCase ? ( r.nextInt( nPasswordSize - 3 ) + 1 ) : 0; // choose a number between 1 and CONSTANT_PASSWORD_SIZE -1
- // no on special characters
- int nNumSpecial = bSpecialCaracters ? ( r.nextInt( nPasswordSize - 2 - nNumCapitalLetters ) + 1 ) : 0; // choose a number beetwen 1 and
- // CONSTANT_PASSWORD_SIZE - a1
- // no of nos
- int nNumNumbers = bNumbers ? ( r.nextInt( nPasswordSize - 1 - nNumCapitalLetters - nNumSpecial ) + 1 ) : 0; // choose a number to complete list of
- // CONSTANT_PASSWORD_SIZE characters
- // no of small
- int nNumSmallLetters = nPasswordSize - nNumCapitalLetters - nNumSpecial - nNumNumbers; // choose a number to complete list of CONSTANT_PASSWORD_SIZE
- // characters
- for ( int j = 0; j < nNumCapitalLetters; j++ )
- {
- char c1 = (char) ( r.nextInt( CONSTANT_NUMBER_LETTERS ) + CONSTANT_ASCII_CODE_A_UPPERCASE );
- listCharacters.add( Character.valueOf( c1 ) );
- }
- for ( int j = 0; j < nNumSmallLetters; j++ )
- {
- char c1 = (char) ( r.nextInt( CONSTANT_NUMBER_LETTERS ) + CONSTANT_ASCII_CODE_A_LOWERCASE );
- listCharacters.add( Character.valueOf( c1 ) );
- }
- for ( int j = 0; j < nNumNumbers; j++ )
- {
- char c1 = (char) ( r.nextInt( CONSTANT_NUMBER_NUMBERS_BASE10 - 1 ) + CONSTANT_ASCII_CODE_ZERO );
- listCharacters.add( Character.valueOf( c1 ) );
- }
- for ( int j = 0; j < nNumSpecial; j++ )
- {
- char c1 = CONSTANT_SPECIAL_CHARACTERS [r.nextInt( CONSTANT_SPECIAL_CHARACTERS.length )];
- listCharacters.add( Character.valueOf( c1 ) );
- }
- Collections.shuffle( listCharacters, r );
- StringBuilder sbPassword = new StringBuilder( listCharacters.size( ) );
- for ( Character myChar : listCharacters )
- {
- sbPassword.append( myChar );
- }
- return sbPassword.toString( );
- }
- /**
- * Check whether a password contains upper and lower case letters, special characters and numbers.
- *
- * @param strPassword
- * The password to check
- * @return True if the password format is correct, false otherwise
- */
- public static boolean checkPasswordFormat( String strPassword )
- {
- return checkPasswordFormat( strPassword, true, true, true );
- }
- /**
- * Check whether a password contains upper and lower case letters, special characters and numbers.
- *
- * @param strPassword
- * The password to check
- * @param bUpperAndLowerCase
- * true if the password must contain upper and lower case
- * @param bNumero
- * if the password must contain numero
- * @param bSpecialCaracters
- * if the password must contain special characters
- *
- * @return True if the password format is correct, false otherwise
- */
- public static boolean checkPasswordFormat( String strPassword, boolean bUpperAndLowerCase, boolean bNumero, boolean bSpecialCaracters )
- {
- if ( ( strPassword == null ) || strPassword.isEmpty( ) )
- {
- return false;
- }
- StringBuilder sbRegex = new StringBuilder( CONSTANT_PASSWORD_BEGIN_REGEX );
- if ( bUpperAndLowerCase )
- {
- sbRegex.append( CONSTANT_PASSWORD_REGEX_UPPER_LOWER );
- }
- if ( bNumero )
- {
- sbRegex.append( CONSTANT_PASSWORD_REGEX_NUM );
- }
- if ( bSpecialCaracters )
- {
- sbRegex.append( CONSTANT_PASSWORD_REGEX_SPECIAL );
- }
- sbRegex.append( CONSTANT_PASSWORD_END_REGEX );
- return strPassword.matches( sbRegex.toString( ) );
- }
- /**
- * Get the maximum valid date of a password starting from now with the given number of days.
- *
- * @param nNumberDay
- * The number of days the password is valid
- * @return The maximum valid date of a password
- */
- public static Timestamp getPasswordMaxValidDate( int nNumberDay )
- {
- if ( nNumberDay <= 0 )
- {
- return null;
- }
- long nMilliSeconds = DateUtil.convertDaysInMiliseconds( nNumberDay );
- return new Timestamp( new java.util.Date( ).getTime( ) + nMilliSeconds );
- }
- }