Password validation - adding additional requirments - java

I have some code that currently checks for minimum and maximum lentgh. I want to also require uppercase, lowercase, special char, and numeric. Any suggestions on what to add to this or where I can find some examples? I've been Googling and looking thru this forum and have been trying to add the additional password requirments and have been unsuccessful.
This is what I want to require.
At least eight characters in length
No more than 20 characters in length
at least lower-case letter and one upper-case
at least one special character from: !##$%^&*()~`-=_+[]{}|:";',./<>?
at least one number [0-9] character
Cannot match the account login name or email address
My current password validation code
public static final int MIN_PASSWORD_LENGTH = 8;
public static final int MAX_PASSWORD_LENGTH = 20;
public static boolean isAcceptablePassword(String password)
{
if(TextUtils.isEmpty(password))
return false;
int len = password.length();
if(len < MIN_PASSWORD_LENGTH || len > MAX_PASSWORD_LENGTH)
return false;
for(int i = 0; i < len; i++)
{
char c = password.charAt(i);
if (Character.isWhitespace(c))
return false;
}
return true;
}

When you're analyzing String data, you should erase the whitespaces on the right and left. This is done by the Strimg#trim function like this:
password = password.trim();
To analize every character of the String, you can transform it to a char array, so it will be easier to fulfill your requirements:
char[] arrPassword = password.toCharArray();
Now you can evaluate a char using these functions: Character#isUpperCase, Character#isLowerCase, Character#isDigit.
Last but not least, you can have a String with the special characters you need to check, and check if the actual character you're evaluating is inside that String. This could be achieved using String#indexOf and String#valueOf, this las one to convert the char to a String type.
Here is a code sample for all this explanation:
public static final String SPECIAL_CHARACTERS = "!##$%^&*()~`-=_+[]{}|:\";',./<>?";
public static final int MIN_PASSWORD_LENGTH = 8;
public static final int MAX_PASSWORD_LENGTH = 20;
public static boolean isAcceptablePassword(String password) {
if (TextUtils.isEmpty(password)) {
System.out.println("empty string.");
return false;
}
password = password.trim();
int len = password.length();
if(len < MIN_PASSWORD_LENGTH || len > MAX_PASSWORD_LENGTH) {
System.out.println("wrong size, it must have at least 8 characters and less than 20.");
return false;
}
char[] aC = password.toCharArray();
for(char c : aC) {
if (Character.isUpperCase(c)) {
System.out.println(c + " is uppercase.");
} else
if (Character.isLowerCase(c)) {
System.out.println(c + " is lowercase.");
} else
if (Character.isDigit(c)) {
System.out.println(c + " is digit.");
} else
if (SPECIAL_CHARACTERS.indexOf(String.valueOf(c)) >= 0) {
System.out.println(c + " is valid symbol.");
} else {
System.out.println(c + " is an invalid character in the password.");
return false;
}
}
return true;
}
The System.out.println(c + " is an invalid character in the password."); sentence is just to check the result of analyze the actual character.

How about some good old regular expressions? This seems to work correctly, although might have made slip in the escaping for special char check
Pattern[] checks = {
Pattern.compile("[!##\\$%^&*()~`\\-=_+\\[\\]{}|:\\\";',\\./<>?]"),
Pattern.compile("\\d+"),
Pattern.compile("[A-Z]+"),
Pattern.compile("[a-z]+"),
Pattern.compile("^.{8,20}$") };
for (String test : new String[] { "password", "Password1",
"Password1&", "toolongtoolongtoolong" }) {
boolean ok = true;
for (Pattern check : checks) {
ok = ok && check.matcher(test).find();
}
System.out.println(test + " " + ok);
}

Stephen is right with a bit of searching you would have found your answers easily around here. But the thread Stephen refers to is using a thirdparty library.
If you want to implement this yourself then before starting the for-loop initialize 4 booleans for your requirements with false. While looping check for all four requirements until one is true. Set the corresponding boolean to true.
How to check the 4 requirements:
The length req you already implemented.
Character(yourChar).isLowerCase()
Character(yourChar).isUpperCase()
Special character: see here: Java String Special character replacement - you can choose a similar approach
After the loop check for the 4 booleans and react accordingly.

Related

how can I check if a string is a floating point number?

In my program I'm going to store user input in an array then going to check each character to see if it's a digit or dot or E or negative sign after that I'll store it in to an array called temps.
Now I have problem in my fleating method () that don't how should I make my condition for the pattern of floating number digit-digit-dot-digit-digit (e.g 12.22)
I have my work here:
public void sorting(String data) {
String[] temps = new String[200];
int cpos = 0;
int tpos = 0;
Arrays.fill(temps, null);
if (str.isEmpty() == false) {
char char1 = str.charAt(cpos);
int i = 0;
while (i < str.length()) {
char1 = str.charAt(cpos);
char1 = str.charAt(tpos);
System.out.println("the current value is " + char1 + " ");
tpos++;
if (Character.isDigit(char1)) {
temps[cpos] = "Digit";
// System.out.println(" this number is digit");
cpos++;
} else if (char1 == 'e' || char1 == 'E') {
temps[cpos] = "s_notaion";
cpos++;
} else if (char1 == '-') {
temps[cpos] = "negative";
cpos++;
} else if (char1 == '.') {
temps[cpos] = ".";
cpos++;
}
i++;
}
}
}
here is the method for floating number
private static boolean floating(String [] data) {
int count =0;
boolean correct = false;
for (int i = 0; i < data.length; i++) {
if (data[i]== "Digit" )
&& data[i]=="." && data[i]"Digit"){
// here is the problem for the condition
}
}
return false;
}
If I understood correctly, the Data array has stuff like ["Digit","Digit",".","Digit"]
So you want the
private static boolean floating(String [] data) {
method to return true if the array only has "Digit" entries and exactly one "." entry? is that it?
If so:
boolean foundLeDigit = false;
for (int i = 0; i < data.length; i++) {
if (data[i].equals("Digit") == false && data[i].equals(".") == false {
//we found something other than a Digit or . it's not a float
return false;
}
if(data[i].equals(".")) {
if(foundLeDigit) { return false; //as we found 2 "." }
foundLeDigit = true
}
}
return foundLeDigit;
The easiest way to test if a String can represent a float is to try to parse it:
String testString = "1.2345";
double result;
try {
result = Double.parseDouble(testString);
System.out.println("Success!")
}
catch (NumberFormatException nfe) {
// wasn't a double, deal with the failure in whatever way you like
}
The questions lacks a bit of context, so for my answer I'm going to presume that this is homework requiring a manual solution, and that all floating point numbers are supposed to be accepted.
Your approach (while over-engineered) is half-right: you are reducing the input string into classes of characters - digit, sign, exponent marker. What is missing is that now you have to make sure that these character classes come in the right order.
Identify the various parts of float numbers (just look at 0, -1.0, 400E30, 42.1E-30) and you'll see that they come in a specific order, even if some are optional, and that each part imposes restrictions on what characters are allowed there. For example, if there is an 'E' in the number, it has to be followed by a number (with optional sign).
So as you step through the characters of the string, think about how you could keep track of where you are in the number, and base your character validation on that (this is the state machine #JonKiparsky was mentioning).
A few small things:
Don't compare strings with '==' - use equalsTo().
Think about what it means if sorting() finds a character which is neither a digit, a sign, or the exponent 'E'?
You allocate the temps array for 200 entries, but the input string could be larger.
using the regular expression is the best way to Handel this problem
private static boolean floating(String [] data) {
int count =0;
boolean correct = false;
for (int i = 0; i < data.length; i++) {
if (str.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")){
System.out.println(" it's a floating number ");
correct= true;
break;
}else
correct = false;
}if (correct ==true){
return true;
}else
return false;
}

Returning a string minus a specific character between specific characters

I am going through the Java CodeBat exercises. Here is the one I am stuck on:
Look for patterns like "zip" and "zap" in the string -- length-3, starting with 'z' and ending with 'p'. Return a string where for all such words, the middle letter is gone, so "zipXzap" yields "zpXzp".
Here is my code:
public String zipZap(String str){
String s = ""; //Initialising return string
String diff = " " + str + " "; //Ensuring no out of bounds exceptions occur
for (int i = 1; i < diff.length()-1; i++) {
if (diff.charAt(i-1) != 'z' &&
diff.charAt(i+1) != 'p') {
s += diff.charAt(i);
}
}
return s;
}
This is successful for a few of them but not for others. It seems like the && operator is acting like a || for some of the example strings; that is to say, many of the characters I want to keep are not being kept. I'm not sure how I would go about fixing it.
A nudge in the right direction if you please! I just need a hint!
Actually it is the other way around. You should do:
if (diff.charAt(i-1) != 'z' || diff.charAt(i+1) != 'p') {
s += diff.charAt(i);
}
Which is equivalent to:
if (!(diff.charAt(i-1) == 'z' && diff.charAt(i+1) == 'p')) {
s += diff.charAt(i);
}
This sounds like the perfect use of a regular expression.
The regex "z.p" will match any three letter token starting with a z, having any character in the middle, and ending in p. If you require it to be a letter you could use "z[a-zA-Z]p" instead.
So you end up with
public String zipZap(String str) {
return str.replaceAll("z[a-zA-Z]p", "zp");
}
This passes all the tests, by the way.
You could make the argument that this question is about raw string manipulation, but I would argue that that makes this an even better lesson: applying regexes appropriately is a massively useful skill to have!
public String zipZap(String str) {
//If bigger than 3, because obviously without 3 variables we just return the string.
if (str.length() >= 3)
{
//Create a variable to return at the end.
String ret = "";
//This is a cheat I worked on to get the ending to work easier.
//I noticed that it wouldn't add at the end, so I fixed it using this cheat.
int minusAmt = 2;
//The minus amount starts with 2, but can be changed to 0 when there is no instance of z-p.
for (int i = 0; i < str.length() - minusAmt; i++)
{
//I thought this was a genius solution, so I suprised myself.
if (str.charAt(i) == 'z' && str.charAt(i+2) == 'p')
{
//Add "zp" to the return string
ret = ret + "zp";
//As long as z-p occurs, we keep the minus amount at 2.
minusAmt = 2;
//Increment to skip over z-p.
i += 2;
}
//If it isn't z-p, we do this.
else
{
//Add the character
ret = ret + str.charAt(i);
//Make the minus amount 0, so that we can get the rest of the chars.
minusAmt = 0;
}
}
//return the string.
return ret;
}
//If it was less than 3 chars, we return the string.
else
{
return str;
}
}

check password for digits and letters

I have problem with two of my methods for password validation.
The method hasDigitsAndLetters is supposed to check whether all the characters of the String are digits and letters and the second method hasTwoDigits is supposed to check whether there are at least two digits in the pass, but the problem is that for expected result true they are ruturning false. If someone can help. here is the code.
//check if the whole string consists of digits and letters
public static boolean hasDigitsAndLetters(String pass)
{
for(int i=0; i<pass.length(); i++)
{
if(!Character.isLetterOrDigit((i)))
{
return false;
}
}
return true;
}
// check whether the password has at least 2 digits
public static boolean hasTwoDigits(String pass)
{
int counter = 0;
for(int i=0; i<pass.length(); i++)
{
if(Character.isDigit(i))
{
counter ++;
}
}
System.out.println("Number of digits: " + counter);
if(counter >= 2)
{
return true;
}
return false;
}
You need to pass character at position i for that String.
Character.isLetterOrDigit((pass.charAt(i)))
same for digit also
Character.isDigit((pass.charAt(i)))
You want to check the character in the string at index i, not the index variable itself:
Character.isLetterOrDigit(pass.charAt(i))
You aren't checking against characters in your pass, you need to change your checks to:
if(!Character.isLetterOrDigit((pass.charAt(i)))
and
if(Character.isDigit(pass.charAt(i)))
Right now you are checking if i is a digit or letter and i is an int. You need to check the character at position i.
if(Character.isDigit(pass.charAt(i)))
The error is that you're comparing the position into the string rather than the character at that position in the string. I'd probably not use charAt, however... there's no point in keeping explicit management of the position here. I suggest you use String.toCharArray instead.
public static boolean isAlphanumeric(final String str) {
for (char c : str.toCharArray()) {
if (!Character.isLetterOrDigit(c)) {
return false;
}
}
return true;
}
public static boolean isBidigital(final String str) {
int n = 0;
for (char c : str.toCharArray()) {
if (Character.isDigit(c)) {
++n;
}
}
return n >= 2;
}

Programming issue at work place related to string

I have a string which is searched based on the delimiter " (double quote).
So when I enter the string "program", it is able to search the beginning and end of the string based on the delimiter and returns me the string program which I put in a vector.
Now, if I enter a string "program"123"" it returns me substrings like program, 123, 123".
Now the result I want is program"123" which is a valid string as per the usecase but it contains " as part of the string and this is where the search by delimiter fails to distinguish between the beginning and end of the string.
Can someone help with some logic?
The following is the method I am using.
enter code here
public static PVector tokenizeInput(final String sCmd)
throws ExceptionOpenQuotedString
{
if (sCmd == null)
{
return null;
}
PVector rc = new PVector();
if (sCmd.length() == 0)
{
rc.add(StringTable.STRING_EMPTY);
return rc;
}
char chCurrent = '\0';
boolean bInWhitespace = true;
boolean bInQuotedToken = false;
boolean bDelim;
int start = 0;
int nLength = sCmd.length();
for (int i = 0; i < nLength; i++)
{
chCurrent = sCmd.charAt(i); // "abcd "ef"" rtns abdc ef ef"
bDelim = -1 != APIParseConstants.CMD_LINE_DELIMS.indexOf(chCurrent);
if (bInWhitespace) // true
{
// In whitespace
if (bDelim)
{
if ('\"' == chCurrent)
{
start = i + 1;
bInQuotedToken = true;
bInWhitespace = false;
} // if ('\"' == chCurrent)
}
else
{
start = i;
bInWhitespace = false;
} // else - if (bDelim)
}
else
{
// Not in whitespace
boolean bAtEnd = i + 1 == nLength;
if (!bDelim)
{
continue;
}
else
{
if ('\"' == chCurrent)
{
if (!bInQuotedToken)
{
// ending current token due to '"'
if (bAtEnd)
{
// non terminated quoted string at end...
throw new ExceptionOpenQuotedString(
sCmd.substring(start));
}
else
{
rc.add(sCmd.substring(start, i)); // include quote
bInQuotedToken = true;
bInWhitespace = false;
} // if (bAtEnd)
}
else
{
// ending quoted string
//if (!bAtEnd)
{
rc.add(sCmd.substring(start, i)); // don't include quote
bInQuotedToken = false;
bInWhitespace = true;
} // if (bAtEnd)
} // else - if (!bInQuotedToken)
}
else
{
// got delim (not '"')
if (!bAtEnd && !bInQuotedToken)
{
rc.add(sCmd.substring(start, i));
bInWhitespace = true;
} // if (bAtEnd)
} // else - if ('\"' == chCurrent)
} // else - if (!bDelim)
} // else - if (bInWhitespace)
} // for (short i = 0; i < nLength; i++)
if (!bInWhitespace && start < nLength)
{
if (!bInQuotedToken || chCurrent == '"')
{
rc.add(sCmd.substring(start));
}
else
{
throw new ExceptionOpenQuotedString(sCmd.substring(start));
} // else - if (!bInQuotedToken)
} // if (!bInWhitespace && start < nLength)
return rc;
}
You should escape the internal ".
Otherwise, you could check for the position of the first and last " characters and split/cut the string using those positions as delimiters.
Whenever you embed one encoding (all possible strings) inside another (quoted strings) there are only a few basic techniques to allow you to parse them unambiguously:
Disallow certain inputs. For instance, don't allow quote characters. Now you know they are always delimiters. In your case, you could choose a new delimiter besides quote and disallow that in your input. This is rarely desirable, because you often end up wanting to allow the input you previously thought you didn't need.
Include the length of the input in the encoding. For example, instead of quotes you could precede each string with the number of characters in it.
Escaping. Some inputs cannot be represented directly. Instead, at least one character is reserved as the escape character. It indicates that whatever follows it should be interpreted in a different way. In Java strings, the backslash is the escape character. If you only need the escape character for a single reason, you may want to follow the example of some SQL dialects and double it. In SQL, a quote is the quote character for strings, so to include a literal quote character in a string, you type two quotes.

Check if String contains only letters

The idea is to have a String read and to verify that it does not contain any numeric characters. So something like "smith23" would not be acceptable.
What do you want? Speed or simplicity? For speed, go for a loop based approach. For simplicity, go for a one liner RegEx based approach.
Speed
public boolean isAlpha(String name) {
char[] chars = name.toCharArray();
for (char c : chars) {
if(!Character.isLetter(c)) {
return false;
}
}
return true;
}
Simplicity
public boolean isAlpha(String name) {
return name.matches("[a-zA-Z]+");
}
Java 8 lambda expressions. Both fast and simple.
boolean allLetters = someString.chars().allMatch(Character::isLetter);
Or if you are using Apache Commons, [StringUtils.isAlpha()].
First import Pattern :
import java.util.regex.Pattern;
Then use this simple code:
String s = "smith23";
if (Pattern.matches("[a-zA-Z]+",s)) {
// Do something
System.out.println("Yes, string contains letters only");
}else{
System.out.println("Nope, Other characters detected");
}
This will output:
Nope, Other characters detected
I used this regex expression (".*[a-zA-Z]+.*"). With if not statement it will avoid all expressions that have a letter before, at the end or between any type of other character.
String strWithLetters = "123AZ456";
if(! Pattern.matches(".*[a-zA-Z]+.*", str1))
return true;
else return false
A quick way to do it is by:
public boolean isStringAlpha(String aString) {
int charCount = 0;
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (aString.length() == 0) {
return false; //zero length string ain't alpha
}
for (int i = 0; i < aString.length(); i++) {
for (int j = 0; j < alphabet.length(); j++) {
if (aString.substring(i, i + 1).equals(alphabet.substring(j, j + 1))
|| aString.substring(i, i + 1).equals(alphabet.substring(j, j + 1).toLowerCase())) {
charCount++;
}
}
if (charCount != (i + 1)) {
System.out.println("\n**Invalid input! Enter alpha values**\n");
return false;
}
}
return true;
}
Because you don't have to run the whole aString to check if it isn't an alpha String.
private boolean isOnlyLetters(String s){
char c=' ';
boolean isGood=false, safe=isGood;
int failCount=0;
for(int i=0;i<s.length();i++){
c = s.charAt(i);
if(Character.isLetter(c))
isGood=true;
else{
isGood=false;
failCount+=1;
}
}
if(failCount==0 && s.length()>0)
safe=true;
else
safe=false;
return safe;
}
I know it's a bit crowded. I was using it with my program and felt the desire to share it with people. It can tell if any character in a string is not a letter or not. Use it if you want something easy to clarify and look back on.
Faster way is below. Considering letters are only a-z,A-Z.
public static void main( String[] args ){
System.out.println(bestWay("azAZpratiyushkumarsinghjdnfkjsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
System.out.println(isAlpha("azAZpratiyushkumarsinghjdnfkjsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
System.out.println(bestWay("azAZpratiyushkumarsinghjdnfkjsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
System.out.println(isAlpha("azAZpratiyushkumarsinghjdnfkjsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
}
public static boolean bettertWay(String name) {
char[] chars = name.toCharArray();
long startTimeOne = System.nanoTime();
for(char c : chars){
if(!(c>=65 && c<=90)&&!(c>=97 && c<=122) ){
System.out.println(System.nanoTime() - startTimeOne);
return false;
}
}
System.out.println(System.nanoTime() - startTimeOne);
return true;
}
public static boolean isAlpha(String name) {
char[] chars = name.toCharArray();
long startTimeOne = System.nanoTime();
for (char c : chars) {
if(!Character.isLetter(c)) {
System.out.println(System.nanoTime() - startTimeOne);
return false;
}
}
System.out.println(System.nanoTime() - startTimeOne);
return true;
}
Runtime is calculated in nano seconds. It may vary system to system.
5748//bettertWay without numbers
true
89493 //isAlpha without numbers
true
3284 //bettertWay with numbers
false
22989 //isAlpha with numbers
false
Check this,i guess this is help you because it's work in my project so once you check this code
if(! Pattern.matches(".*[a-zA-Z]+.*[a-zA-Z]", str1))
{
String not contain only character;
}
else
{
String contain only character;
}
String expression = "^[a-zA-Z]*$";
CharSequence inputStr = str;
Pattern pattern = Pattern.compile(expression);
Matcher matcher = pattern.matcher(inputStr);
if(matcher.matches())
{
//if pattern matches
}
else
{
//if pattern does not matches
}
Try using regular expressions: String.matches
public boolean isAlpha(String name)
{
String s=name.toLowerCase();
for(int i=0; i<s.length();i++)
{
if((s.charAt(i)>='a' && s.charAt(i)<='z'))
{
continue;
}
else
{
return false;
}
}
return true;
}
Feels as if our need is to find whether the character are only alphabets.
Here's how you can solve it-
Character.isAlphabetic(c)
helps to check if the characters of the string are alphabets or not.
where c is
char c = s.charAt(elementIndex);
While there are many ways to skin this cat, I prefer to wrap such code into reusable extension methods that make it trivial to do going forward. When using extension methods, you can also avoid RegEx as it is slower than a direct character check. I like using the extensions in the Extensions.cs NuGet package. It makes this check as simple as:
Add the https://www.nuget.org/packages/Extensions.cs package to your project.
Add "using Extensions;" to the top of your code.
"smith23".IsAlphabetic() will return False whereas "john smith".IsAlphabetic() will return True. By default the .IsAlphabetic() method ignores spaces, but it can also be overridden such that "john smith".IsAlphabetic(false) will return False since the space is not considered part of the alphabet.
Every other check in the rest of the code is simply MyString.IsAlphabetic().
To allow only ASCII letters, the character class \p{Alpha} can be used. (This is equivalent to [\p{Lower}\p{Upper}] or [a-zA-Z].)
boolean allLettersASCII = str.matches("\\p{Alpha}*");
For allowing all Unicode letters, use the character class \p{L} (or equivalently, \p{IsL}).
boolean allLettersUnicode = str.matches("\\p{L}*");
See the Pattern documentation.
I found an easy of way of checking a string whether all its digit is letter or not.
public static boolean isStringLetter(String input) {
boolean b = false;
for (int id = 0; id < input.length(); id++) {
if ('a' <= input.charAt(id) && input.charAt(id) <= 'z') {
b = true;
} else if ('A' <= input.charAt(id) && input.charAt(id) <= 'Z') {
b = true;
} else {
b = false;
}
}
return b;
}
I hope it could help anyone who is looking for such method.
Use StringUtils.isAlpha() method and it will make your life simple.

Categories