Generate a random string with specific requirements



I am trying to generate OTP with following specific conditions:

  1. OTP must have at least 1 lower case character.
  2. OTP must have at least 1 upper case character
  3. OTP must have at least must have 1 or 2 number
  4. OTP length should be 8 character.

I tried following ways

import java.security.SecureRandom;
import org.apache.commons.lang3.RandomStringUtils;

public class TestJava {
    public static void main(String []args){
        char[] allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
        SecureRandom random = new SecureRandom();
        int SIZE = 8;
        // Try- 1
        String opt1 = RandomStringUtils.random(SIZE, 0, 0, true, true, allowedChars, random);
        // Try - 2
        String opt2 = RandomStringUtils.randomAlphanumeric(8);
        // Try - 3
        String opt3 = RandomStringUtils.random(8, true, true);
    }
}

Also tried solutions from https://www.techiedelight.com/generate-random-alphanumeric-password-java/

But after 4-5 tries it is generating password without number(s), i.e. condition 3 is not satisfying.

So can you please let me know how can I achieve given functionality. Thanks.

Answer

Could try the following and have a generated string within given condition.
Some further optimization on code can be done also, but notice every character have a fair probability of occurrence after mandatory condition are achieved (except length which is stop condition)

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class RandomStr 
{
    public static void main(String args[]) 
    {
        RandomStr r = new RandomStr();
        for(int i=0;i<10;i++)
            System.out.println(r.new MyRandom().getRandom());
    }
    class MyRandom
    {
        char[] upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
        char[] lower = "abcdefghijklmnopqrstuvwxyz".toCharArray();
        int Size = 8;
        
        
        public String getRandom()
        {
            String str="";
            boolean flag= true;
            while(flag)
            {
                if(str.length()<2 && flag==true)
                {
                    str+=(int)(10*Math.random());
                    flag = ((int)(2*Math.random())==1) ? true : false;
                }
                else
                {
                    flag = false;
                }
            }
            str += upper[(int)(upper.length*Math.random())];
            str += lower[(int)(lower.length*Math.random())];
            
            while(str.length()<8)
                str+= ((int)(2*Math.random())==1) ? upper[(int)(upper.length*Math.random())] : lower[(int)(upper.length*Math.random())];
            //reorder string
            List<Character> list= new ArrayList<Character>();
            char[] cList= str.toCharArray();
            for(int i=0;i<cList.length;i++)
                list.add(cList[i]);
            Collections.shuffle(list);
            str="";
            for(char c: list)
            {
                str+=c;
            }
            return str;
        }
        
    }
}

Output:

7OROFjHM
3Sn2jlki
QsTf6IYB
Ps09QrbN
93OdRlOX
6JBSdjdk
mg4Qtk0J
Dp31nHJQ
RrDnkYH5
Ik4ed3se


Source: stackoverflow