I am in the process of creating a java Web Application, to do enable users to create fair strong credentials I would like to prevent them from entering weak passwords. I'd like to follow the basic rules of it must contain at least eight characters and at least one number and one symbol. I would appreciate a point in the right direction, many thanks!
Two solutions :
1.) You can use regular expression for the password requirements and compare the password entered by the user with that expression, if the pattern of password matches the regular expression then you can let the user register otherwise you can show an error.
2.) When user enters a password, you can call a function which would check whether:
a. password contains at least one number.
b. password contains at least one special character.
c. is the length of password entered by user greater than the minimum length etc...
this function will return true or false depending on whether password is accepted or not.
Hope this helps you.
You can check user's entered password by this java-code,
public static boolean isValidPassword(String userEnteredPassword) {
boolean atleastOneUpper = false;
boolean atleastOneLower = false;
boolean atleastOneDigit = false;
if (userEnteredPassword.length() < 8) { // If its less then 8 characters, its automatically not valid
return false;
}
for (int i = 0; i < userEnteredPassword.length(); i++) { // Lets iterate over only once. Saving time
if (Character.isUpperCase(userEnteredPassword.charAt(i))) {
atleastOneUpper = true;
}
else if (Character.isLowerCase(userEnteredPassword.charAt(i))) {
atleastOneLower = true;
}
else if (Character.isDigit(userEnteredPassword.charAt(i))) {
atleastOneDigit = true;
}
}
return (atleastOneUpper && atleastOneLower && atleastOneDigit); // Return true IFF the userEnteredPassword is atleast eight characters long, has atleast one upper, lower and digit
}
Related
I was working on a Java coding problem and encountered the following issue.
Problem:
Given a string, does "xyz" appear in the middle of the string? To define middle, we'll say that the number of chars to the left and right of the "xyz" must differ by at most one
xyzMiddle("AAxyzBB") → true
xyzMiddle("AxyzBBB") → false
My Code:
public boolean xyzMiddle(String str) {
boolean result=false;
if(str.length()<3)result=false;
if(str.length()==3 && str.equals("xyz"))result=true;
for(int j=0;j<str.length()-3;j++){
if(str.substring(j,j+3).equals("xyz")){
String rightSide=str.substring(j+3,str.length());
int rightLength=rightSide.length();
String leftSide=str.substring(0,j);
int leftLength=leftSide.length();
int diff=Math.abs(rightLength-leftLength);
if(diff>=0 && diff<=1)result=true;
else result=false;
}
}
return result;
}
Output I am getting:
Running for most of the test cases but failing for certain edge cases involving more than once occurence of "xyz" in the string
Example:
xyzMiddle("xyzxyzAxyzBxyzxyz")
My present method is taking the "xyz" starting at the index 0. I understood the problem. I want a solution where the condition is using only string manipulation functions.
NOTE: I need to solve this using string manipulations like substrings. I am not considering using list, stringbuffer/builder etc. Would appreciate answers which can build up on my code.
There is no need to loop at all, because you only want to check if xyz is in the middle.
The string is of the form
prefix + "xyz" + suffix
The content of the prefix and suffix is irrelevant; the only thing that matters is they differ in length by at most 1.
Depending on the length of the string (and assuming it is at least 3):
Prefix and suffix must have the same length if the (string's length - the length of xyz) is even. In this case:
int prefixLen = (str.length()-3)/2;
result = str.substring(prefixLen, prefixLen+3).equals("xyz");
Otherwise, prefix and suffix differ in length by 1. In this case:
int minPrefixLen = (str.length()-3)/2;
int maxPrefixLen = minPrefixLen+1;
result = str.substring(minPrefixLen, minPrefixLen+3).equals("xyz") || str.substring(maxPrefixLen, maxPrefixLen+3).equals("xyz");
In fact, you don't even need the substring here. You can do it with str.regionMatches instead, and avoid creating the substrings, e.g. for the first case:
result = str.regionMatches(prefixLen, "xyz", 0, 3);
Super easy solution:
Use Apache StringUtils to split the string.
Specifically, splitByWholeSeparatorPreserveAllTokens.
Think about the problem.
Specifically, if the token is in the middle of the string then there must be an even number of tokens returned by the split call (see step 1 above).
Zero counts as an even number here.
If the number of tokens is even, add the lengths of the first group (first half of the tokens) and compare it to the lengths of the second group.
Pay attention to details,
an empty token indicates an occurrence of the token itself.
You can count this as zero length, count as the length of the token, or count it as literally any number as long as you always count it as the same number.
if (lengthFirstHalf == lengthSecondHalf) token is in middle.
Managing your code, I left unchanged the cases str.lengt<3 and str.lengt==3.
Taking inspiration from #Andy's answer, I considered the pattern
prefix+'xyz'+suffix
and, while looking for matches I controlled also if they respect the rule IsMiddle, as you defined it. If a match that respect the rule is found, the loop breaks and return a success, else the loop continue.
public boolean xyzMiddle(String str) {
boolean result=false;
if(str.length()<3)
result=false;
else if(str.length()==3 && str.equals("xyz"))
result=true;
else{
int preLen=-1;
int sufLen=-2;
int k=0;
while(k<str.lenght){
if(str.indexOf('xyz',k)!=-1){
count++;
k=str.indexOf('xyz',k);
//check if match is in the middle
preLen=str.substring(0,k).lenght;
sufLen=str.substring(k+3,str.lenght-1).lenght;
if(preLen==sufLen || preLen==sufLen-1 || preLen==sufLen+1){
result=true;
k=str.length; //breaks the while loop
}
else
result=false;
}
else
k++;
}
}
return result;
}
This is the assignment I'm working on right now...
Implement a program that reads in a user password and verifies it meets the following criteria:
Is atleast 8 characters long
Contains atleast 1 lower letter character
Contains atleast 1 upper letter character
Contains atleast 1 numeric digit
Contains atleast 1 special character from the set: !##$%^&*
Does not contain the word “and” or the word “end”
Output a string that prompts the user for a password and include the requirements
above in your output.
Output a string that states valid or invalid. If invalid, state which rule above has not been met.
Utilize the following functionality:
indexOf
Looping structure
charAt()
isDigit()
isUpperCase()
isLowerCase()
and any additional functionality needed
The tricky part to me is that it has to return with all of the things that are missing. Like if I put in a password that says password, it should come back and tell me "you're missing an upper case, a digit, and a special character"
I have a start, but I'm really confused on how to get it to return something to me.
This is what i have so far
/********************************************
This program will test a password for:
8 characters
1 upper case
1 lower case
1 numeric digit
1 special character from the set !##$%^&*
and make sure it doesn't contain AND or END
If the password complies, it will return a valid answer
If not, it will tell the user what they need to do.
*********************************************/
import java.util.Scanner;
public class YoungAmyProg5
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
String input;
//input password
System.out.println("Enter a password that follows these rules:\n Is at least 8 characters long\n Contains at least 1 lower case letter\n Contains at least 1 upper case letter\n Contains at least 1 numeric digit\n Contains at least 1 special character from the set: ! ##$%^&*\n Does NOT contain the word "and" or the word "end": ")
input= in.nextLine ();
//Put through string and reply
if
public static boolean isSecurePassword(String password) {
int lengthPassword = password.length();
if (lengthPassword >= 8 ) {
return false;
}
boolean hasUppercase = false; //uppercase
boolean hasLowecase = false; //lowercase
boolean hasDigit = false; //digit
int specialChar = input.indexOf('!', '#', '#', '$', '%', '^', '&', '*'); //special character
int word = input.indexOf ('and', 'end'); //and or end
for (int i = 0; i < lengthPassword; i++) {
char ch = password.charAt(i);
if (Character.isUpperCase(ch) ) {
hasUppercase = true;
}
if (Character.isLowerCase(ch) ) {
hasLowercase = true;
}
if (Character.isDigit(ch) ) {
hasDigit = true;
}
if (specialChar>0) {
specialChar = true;
}
if (word>0) {
word = true;
}
Instead of setting variables, you could also create a list that stores missing things and a boolean too check if error occured:
List<String> missing = new ArrayList<String>();
boolean verified = true;
And inside your if-statements, if somethíng is wrong, set verified to false and add a string like 'an upper case letter' to the list.
if( <password does NOT contain an upper case letter> )
missing.add("an upper case letter");
verified = false;
}
After all if-statements just check if verified is true, if not generate a string and add all strings from the missing list to it. (Generate the sentence)
(I know this will end in a somewhat long code and that it is not too efficient)
Maybe you can think in another way: when you find a reqiurement is violated, return false; if finally turns out no violation, return true.
I am new in android and trying to make a calculator...
Now i have extracted whole expression in a charSequence variable.
e.g 30+69-(3-10)
Now i need to detect whether the first character of charSequence variable is either a number (0-9) or a character/operator.
i can use get.subSequence(0,1) but dont want to compare it with every number to decide whether its a number or not and if its a number then which one it is....
How can i compare it with every number using fewer conditions and also extract that specific number....
You can use:
Character.isDigit(someChar)
This will tell you if a char is a number or not.
If it is not, you can assume it is an operator and treat it as such.
So an implementation could look like:
CharSequence chars = "1+2-3";
for(int i = 0; i < chars.length(); i++ ) {
if (Character.isDigit(chars.charAt(i))) {
//is digit
} else {
//is operator
}
}
*I don't have a java compiler available, so I cant promise that works at the moment.
I would like to find an efficient way (not scanning the String 10,000 times, or creating lots of intermediary Strings for holding temporary results, or string bashing, etc.) to write a method that accepts a String and determine if it meets the following criteria:
It is at least 2 characters in length
The first character is uppercased
The remaining substring after the first character contains at least 1 lowercased character
Here's my attempt so far:
private boolean isInProperForm(final String token) {
if(token.length() < 2)
return false;
char firstChar = token.charAt(0);
String restOfToken = token.substring(1);
String firstCharAsString = firstChar + "";
String firstCharStrToUpper = firstCharAsString.toUpperCase();
// TODO: Giving up because this already seems way too complicated/inefficient.
// Ignore the '&& true' clause - left it there as a placeholder so it wouldn't give a compile error.
if(firstCharStrToUpper.equals(firstCharAsString) && true)
return true;
// Presume false if we get here.
return false;
}
But as you can see I already have 1 char and 3 temp strings, and something just doesn't feel right. There's got to be a better way to write this. It's important because this method is going to get called thousands and thousands of times (for each tokenized word in a text document). So it really really needs to be efficient.
Thanks in advance!
This function should cover it. Each char is examined only once and no objects are created.
public static boolean validate(String token) {
if (token == null || token.length() < 2) return false;
if (!Character.isUpperCase(token.charAt(0)) return false;
for (int i = 1; i < token.length(); i++)
if (Character.isLowerCase(token.charAt(i)) return true;
return false;
The first criteria is simply the length - this data is cached in the string object and is not requiring traversing the string.
You can use Character.isUpperCase() to determine if the first char is upper case. No need as well to traverse the string.
The last criteria requires a single traversal on the string- and stop when you first find a lower case character.
P.S. An alternative for the 2+3 criteria combined is to use a regex (not more efficient - but more elegant):
return token.matches("[A-Z].*[a-z].*");
The regex is checking if the string starts with an upper case letter, and then followed by any sequence which contains at least one lower case character.
It is at least 2 characters in length
The first character is
uppercased
The remaining substring after the first character contains
at least 1 lowercased character
Code:
private boolean isInProperForm(final String token) {
if(token.length() < 2) return false;
if(!Character.isUpperCase(token.charAt(0)) return false;
for(int i = 1; i < token.length(); i++) {
if(Character.isLowerCase(token.charAt(i)) {
return true; // our last criteria, so we are free
// to return on a met condition
}
}
return false; // didn't meet the last criteria, so we return false
}
If you added more criteria, you'd have to revise the last condition.
What about:
return token.matches("[A-Z].*[a-z].*");
This regular expression starts with an uppercase letter and has at least one following lowercase letter and therefore meets your requirements.
To find if the first character is uppercase:
Character.isUpperCase(token.charAt(0))
To check if there is at least one lowercase:
if(Pattern.compile("[a-z]").matcher(token).find()) {
//At least one lowercase
}
To check if first char is uppercase you can use:
Character.isUpperCase(s.charAt(0))
return token.matches("[A-Z].[a-z].");
I am trying to use the matches() function to check a user-entered password for certain conditions
"Contains six alphanumeric characters, at least one letter and one number"
Here is my current condition for checking for alphanumeric characters
pword.matches("([[a-zA-Z]&&0-9])*")
unfortunately in example using "rrrrZZ1" as the password this condition still returns false
What would be the correct regular expression? Thank you
Someone else here may prove me wrong, but this is going to be very difficult to do without an excessively complex regular expression. I'd just use a non-regular expression approach instead. Set 3 booleans for each of your conditions, loop through the characters and set each boolean as each condition is met, and if all 3 booleans don't equal true, then fail the verification.
You could use something as simple as this:
public boolean validatePassword(String password){
if(password.length() < 6){
return false;
}
boolean foundLetter = false;
boolean foundNumber = false;
for(int i=0; i < password.length(); i++){
char c = password.charAt(i);
if(Character.isLetter(c)){
foundLetter = true;
}else if(Character.isDigit(c)){
foundNumber = true;
}else{
// Isn't alpha-numeric.
return false;
}
}
return foundLetter && foundNumber;
}
I agree with ziesemer - use a validatePassword() method instead of cramming it into regex.
Much more readable for a developer to maintain.
If you do want to go down the regex path, it is achievable using zero width positive lookaheads.
Contains six characters, at least one letter and one number:
^.*(?=.{6,})(?=.*[a-zA-Z]).*$
I changed your six alphanumeric characters to just characters.
Supports more complex passwords :)
Great post on the topic:
http://www.zorched.net/2009/05/08/password-strength-validation-with-regular-expressions/
Bookmark this one too:
http://www.regular-expressions.info/