Skip to content

Commit 0b668c1

Browse files
committed
Added: Password Validation using passay API.
1 parent d2492cb commit 0b668c1

File tree

5 files changed

+201
-98
lines changed

5 files changed

+201
-98
lines changed

Diff for: pom.xml

+111-95
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,117 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4-
<modelVersion>4.0.0</modelVersion>
5-
<parent>
6-
<groupId>org.springframework.boot</groupId>
7-
<artifactId>spring-boot-starter-parent</artifactId>
8-
<version>3.0.5</version>
9-
<relativePath/> <!-- lookup parent from repository -->
10-
</parent>
11-
<groupId>com.alibou</groupId>
12-
<artifactId>security</artifactId>
13-
<version>0.0.1-SNAPSHOT</version>
14-
<name>security</name>
15-
<description>Demo project for Spring Boot</description>
16-
<properties>
17-
<java.version>17</java.version>
18-
</properties>
19-
<dependencies>
20-
<dependency>
21-
<groupId>org.springframework.boot</groupId>
22-
<artifactId>spring-boot-starter-data-jpa</artifactId>
23-
</dependency>
24-
<dependency>
25-
<groupId>org.springframework.boot</groupId>
26-
<artifactId>spring-boot-starter-security</artifactId>
27-
</dependency>
28-
<dependency>
29-
<groupId>org.springframework.boot</groupId>
30-
<artifactId>spring-boot-starter-web</artifactId>
31-
</dependency>
32-
<dependency>
33-
<groupId>com.mysql</groupId>
34-
<artifactId>mysql-connector-j</artifactId>
35-
<scope>runtime</scope>
36-
</dependency>
37-
<dependency>
38-
<groupId>org.projectlombok</groupId>
39-
<artifactId>lombok</artifactId>
40-
<optional>true</optional>
41-
</dependency>
42-
<dependency>
43-
<groupId>io.jsonwebtoken</groupId>
44-
<artifactId>jjwt-api</artifactId>
45-
<version>0.11.5</version>
46-
</dependency>
47-
<dependency>
48-
<groupId>io.jsonwebtoken</groupId>
49-
<artifactId>jjwt-impl</artifactId>
50-
<version>0.11.5</version>
51-
</dependency>
52-
<dependency>
53-
<groupId>io.jsonwebtoken</groupId>
54-
<artifactId>jjwt-jackson</artifactId>
55-
<version>0.11.5</version>
56-
</dependency>
57-
<dependency>
58-
<groupId>org.springdoc</groupId>
59-
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
60-
<version>2.1.0</version>
61-
</dependency>
62-
<dependency>
63-
<groupId>org.springframework.boot</groupId>
64-
<artifactId>spring-boot-starter-validation</artifactId>
65-
</dependency>
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>org.springframework.boot</groupId>
7+
<artifactId>spring-boot-starter-parent</artifactId>
8+
<version>3.0.5</version>
9+
<relativePath/> <!-- lookup parent from repository -->
10+
</parent>
11+
<groupId>com.alibou</groupId>
12+
<artifactId>security</artifactId>
13+
<version>0.0.1-SNAPSHOT</version>
14+
<name>security</name>
15+
<description>Demo project for Spring Boot</description>
16+
<properties>
17+
<java.version>17</java.version>
18+
</properties>
19+
<dependencies>
20+
<dependency>
21+
<groupId>org.springframework.boot</groupId>
22+
<artifactId>spring-boot-starter-data-jpa</artifactId>
23+
</dependency>
24+
<dependency>
25+
<groupId>org.springframework.boot</groupId>
26+
<artifactId>spring-boot-starter-security</artifactId>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-starter-web</artifactId>
31+
</dependency>
32+
<dependency>
33+
<groupId>com.mysql</groupId>
34+
<artifactId>mysql-connector-j</artifactId>
35+
<scope>runtime</scope>
36+
</dependency>
37+
<dependency>
38+
<groupId>org.projectlombok</groupId>
39+
<artifactId>lombok</artifactId>
40+
<optional>true</optional>
41+
</dependency>
42+
<dependency>
43+
<groupId>io.jsonwebtoken</groupId>
44+
<artifactId>jjwt-api</artifactId>
45+
<version>0.11.5</version>
46+
</dependency>
47+
<dependency>
48+
<groupId>io.jsonwebtoken</groupId>
49+
<artifactId>jjwt-impl</artifactId>
50+
<version>0.11.5</version>
51+
</dependency>
52+
<dependency>
53+
<groupId>io.jsonwebtoken</groupId>
54+
<artifactId>jjwt-jackson</artifactId>
55+
<version>0.11.5</version>
56+
</dependency>
57+
<dependency>
58+
<groupId>org.springdoc</groupId>
59+
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
60+
<version>2.1.0</version>
61+
</dependency>
62+
<dependency>
63+
<groupId>org.springframework.boot</groupId>
64+
<artifactId>spring-boot-starter-validation</artifactId>
65+
</dependency>
6666

67-
<dependency>
68-
<groupId>org.springframework.boot</groupId>
69-
<artifactId>spring-boot-starter-test</artifactId>
70-
<scope>test</scope>
71-
</dependency>
72-
<dependency>
73-
<groupId>org.springframework.security</groupId>
74-
<artifactId>spring-security-test</artifactId>
75-
<scope>test</scope>
76-
</dependency>
77-
<dependency>
78-
<groupId>org.apache.poi</groupId>
79-
<artifactId>poi-ooxml</artifactId>
80-
<version>5.2.3</version>
81-
</dependency>
82-
</dependencies>
67+
<dependency>
68+
<groupId>org.springframework.boot</groupId>
69+
<artifactId>spring-boot-starter-test</artifactId>
70+
<scope>test</scope>
71+
</dependency>
72+
<dependency>
73+
<groupId>org.springframework.security</groupId>
74+
<artifactId>spring-security-test</artifactId>
75+
<scope>test</scope>
76+
</dependency>
77+
<dependency>
78+
<groupId>org.apache.poi</groupId>
79+
<artifactId>poi-ooxml</artifactId>
80+
<version>5.2.3</version>
81+
</dependency>
82+
<dependency>
83+
<groupId>com.google.zxing</groupId>
84+
<artifactId>core</artifactId>
85+
<version>3.5.1</version>
86+
</dependency>
8387

84-
<build>
85-
<plugins>
86-
<plugin>
87-
<groupId>org.springframework.boot</groupId>
88-
<artifactId>spring-boot-maven-plugin</artifactId>
89-
<configuration>
90-
<excludes>
91-
<exclude>
92-
<groupId>org.projectlombok</groupId>
93-
<artifactId>lombok</artifactId>
94-
</exclude>
95-
</excludes>
96-
</configuration>
97-
</plugin>
98-
</plugins>
99-
</build>
88+
<dependency>
89+
<groupId>com.google.zxing</groupId>
90+
<artifactId>javase</artifactId>
91+
<version>3.5.0</version>
92+
</dependency>
93+
<dependency>
94+
<groupId>org.passay</groupId>
95+
<artifactId>passay</artifactId>
96+
<version>1.6.3</version>
97+
</dependency>
98+
</dependencies>
99+
100+
<build>
101+
<plugins>
102+
<plugin>
103+
<groupId>org.springframework.boot</groupId>
104+
<artifactId>spring-boot-maven-plugin</artifactId>
105+
<configuration>
106+
<excludes>
107+
<exclude>
108+
<groupId>org.projectlombok</groupId>
109+
<artifactId>lombok</artifactId>
110+
</exclude>
111+
</excludes>
112+
</configuration>
113+
</plugin>
114+
</plugins>
115+
</build>
100116

101117
</project>

Diff for: src/main/java/com/ganesh/security/payload/request/AuthenticationRequest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.ganesh.security.payload.request;
22

3+
import com.ganesh.security.validation.ValidPassword;
34
import jakarta.validation.constraints.Email;
45
import jakarta.validation.constraints.NotBlank;
56
import jakarta.validation.constraints.Size;
@@ -18,6 +19,6 @@ public class AuthenticationRequest {
1819
@Size(max = 50)
1920
private String email;
2021

21-
@NotBlank
22+
@ValidPassword
2223
private String password;
2324
}

Diff for: src/main/java/com/ganesh/security/payload/request/RegisterRequest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.ganesh.security.payload.request;
22

33
import com.ganesh.security.models.user.Role;
4+
import com.ganesh.security.validation.ValidPassword;
45
import jakarta.validation.constraints.Email;
56
import jakarta.validation.constraints.NotBlank;
67
import jakarta.validation.constraints.Size;
@@ -27,8 +28,7 @@ public class RegisterRequest {
2728
@Size(max = 50)
2829
private String email;
2930

30-
@NotBlank
31-
@Size(min = 3, max = 20)
31+
@ValidPassword
3232
private String password;
3333

3434
private Role role;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.ganesh.security.validation;
2+
3+
import jakarta.validation.ConstraintValidator;
4+
import jakarta.validation.ConstraintValidatorContext;
5+
import org.passay.*;
6+
7+
import java.util.Arrays;
8+
import java.util.List;
9+
10+
/**
11+
* @author Ganesh babu
12+
* @Since 09-09-2023
13+
* Visit: <a href="https://stackabuse.com/spring-custom-password-validation/">.Link..</a>
14+
*/
15+
16+
public class PasswordConstraintValidator implements ConstraintValidator<ValidPassword, String> {
17+
@Override
18+
public void initialize(ValidPassword constraintAnnotation) {
19+
ConstraintValidator.super.initialize(constraintAnnotation);
20+
}
21+
22+
@Override
23+
public boolean isValid(
24+
String password,
25+
ConstraintValidatorContext constraintValidatorContext) {
26+
PasswordValidator validator = new PasswordValidator(Arrays.asList(
27+
// at least 8 characters
28+
new LengthRule(8, 30),
29+
30+
// at least one upper-case character
31+
new CharacterRule(EnglishCharacterData.UpperCase, 1),
32+
33+
// at least one lower-case character
34+
new CharacterRule(EnglishCharacterData.LowerCase, 1),
35+
36+
// at least one digit character
37+
new CharacterRule(EnglishCharacterData.Digit, 1),
38+
39+
// at least one symbol (special character)
40+
new CharacterRule(EnglishCharacterData.Special, 1),
41+
42+
// no whitespace
43+
new WhitespaceRule()
44+
45+
));
46+
RuleResult result = validator.validate(new PasswordData(password));
47+
48+
if (result.isValid()) return true;
49+
50+
List<String> messages = validator.getMessages(result);
51+
String messageTemplate = String.join(",", messages);
52+
constraintValidatorContext
53+
.buildConstraintViolationWithTemplate(messageTemplate)
54+
.addConstraintViolation()
55+
.disableDefaultConstraintViolation();
56+
57+
return false;
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.ganesh.security.validation;
2+
3+
import jakarta.validation.Constraint;
4+
import jakarta.validation.Payload;
5+
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.Target;
8+
9+
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
10+
import static java.lang.annotation.ElementType.FIELD;
11+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
12+
13+
/*
14+
* Visit: <a href="https://stackabuse.com/spring-custom-password-validation/">.Link..</a>
15+
* */
16+
17+
@Constraint(validatedBy = PasswordConstraintValidator.class)
18+
@Target({FIELD, ANNOTATION_TYPE})
19+
@Retention(RUNTIME)
20+
public @interface ValidPassword {
21+
22+
String message() default "Invalid Password";
23+
24+
Class<?>[] groups() default {};
25+
26+
Class<? extends Payload>[] payload() default {};
27+
}

0 commit comments

Comments
 (0)