diff options
| author | Kamal Wickramanayake <kamal@inbox.lk> | 2026-06-13 21:03:31 +0530 |
|---|---|---|
| committer | Kamal Wickramanayake <kamal@inbox.lk> | 2026-06-13 21:03:31 +0530 |
| commit | f0001c5c8d8a33729b93d8d6e10d3af40bfabed6 (patch) | |
| tree | 6042e5bfdd48671daa95baf29c5041e526f5b62e /spring-boot/09-spring-security-db-authentication/src/main/java | |
| parent | 6ae21cd4e51756ea14b43b82a9d500bca9fb8032 (diff) | |
Added sample application 09-spring-security-db-authentication
Diffstat (limited to 'spring-boot/09-spring-security-db-authentication/src/main/java')
8 files changed, 211 insertions, 0 deletions
diff --git a/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/Application.java b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/Application.java new file mode 100644 index 0000000..4393f3f --- /dev/null +++ b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/Application.java @@ -0,0 +1,12 @@ +package com.example.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) throws Exception { + SpringApplication.run(Application.class, args); + } +}
\ No newline at end of file diff --git a/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/HomeController.java b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/HomeController.java new file mode 100644 index 0000000..d6ead56 --- /dev/null +++ b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/HomeController.java @@ -0,0 +1,13 @@ +package com.example.spring; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class HomeController { + + @RequestMapping("/") + public String home() { + return "index"; + } +} diff --git a/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/config/SecurityConfig.java b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/config/SecurityConfig.java new file mode 100644 index 0000000..1f400d5 --- /dev/null +++ b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/config/SecurityConfig.java @@ -0,0 +1,16 @@ +package com.example.spring.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.argon2.Argon2PasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + // An Argon2 password encoder with a salt length of 16 bytes, a hash length of 32 bytes, parallelism of 1, memory cost of 1 << 14 (i.e. 16MB) and 2 iterations. + return Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8(); + } +}
\ No newline at end of file diff --git a/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/contact/controller/ContactController.java b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/contact/controller/ContactController.java new file mode 100644 index 0000000..6d5e9b4 --- /dev/null +++ b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/contact/controller/ContactController.java @@ -0,0 +1,34 @@ +package com.example.spring.contact.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; + +import jakarta.validation.Valid; + +@Controller +public class ContactController { + + @GetMapping("/contact") + public String showForm(Model model) { + model.addAttribute("contactForm", new ContactForm()); + return "contact/form"; + } + + @PostMapping("/contact") + public String processSubmission(@Valid @ModelAttribute ContactForm contactForm, BindingResult bindingResult, + Model model) { + if (bindingResult.hasErrors()) { + return "contact/form"; + } + + // Do whatever needed with the submitted data here. + // For example, invoke a method in a service/componet bean to send an email to contact person. + + return "contact/result"; + } + +} diff --git a/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/contact/controller/ContactForm.java b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/contact/controller/ContactForm.java new file mode 100644 index 0000000..925999b --- /dev/null +++ b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/contact/controller/ContactForm.java @@ -0,0 +1,45 @@ +package com.example.spring.contact.controller; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; + +public class ContactForm { + + @Pattern(regexp = "^[ a-zA-Z]+$", message = "Name should only include English letters") + @NotBlank(message = "Name is required") + private String name; + + @Email(message = "Must be a valid email") + @NotBlank(message = "Email is required") + private String email; + + @Size(min = 10, message = "Message must be at least 10 characters long") + private String message; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + +} diff --git a/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/user/entity/User.java b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/user/entity/User.java new file mode 100644 index 0000000..a8ec6d2 --- /dev/null +++ b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/user/entity/User.java @@ -0,0 +1,53 @@ +package com.example.spring.user.entity; + +import java.util.ArrayList; +import java.util.Collection; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +/* + @Table - Used to set the database table name explicitely. +*/ +@Entity +@Table(name="user_account") +public class User implements UserDetails { + + /* + GenerationType.IDENTITY - Auto generate value based on database's native auto increment feature + */ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(unique = true) + private String username; + + private String password; + + /* + Roles and permissions can be represented by GrantedAuthority instances. + */ + @Override + public Collection<? extends GrantedAuthority> getAuthorities() { + return new ArrayList<>(); + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getUsername() { + return username; + } + +} diff --git a/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/user/repository/UserRepository.java b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/user/repository/UserRepository.java new file mode 100644 index 0000000..f719637 --- /dev/null +++ b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/user/repository/UserRepository.java @@ -0,0 +1,13 @@ +package com.example.spring.user.repository; + +import java.util.Optional; + +import org.springframework.data.repository.ListCrudRepository; +import org.springframework.stereotype.Repository; + +import com.example.spring.user.entity.User; + +@Repository +public interface UserRepository extends ListCrudRepository<User, Long> { + Optional<User> findByUsername(String username); +} diff --git a/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/user/service/CustomUserDetailsService.java b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/user/service/CustomUserDetailsService.java new file mode 100644 index 0000000..c61649e --- /dev/null +++ b/spring-boot/09-spring-security-db-authentication/src/main/java/com/example/spring/user/service/CustomUserDetailsService.java @@ -0,0 +1,25 @@ +package com.example.spring.user.service; + +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import com.example.spring.user.repository.UserRepository; + +@Service +public class CustomUserDetailsService implements UserDetailsService { + + private final UserRepository userRepository; + + public CustomUserDetailsService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + return userRepository.findByUsername(username) + .orElseThrow(() -> new UsernameNotFoundException("User not found")); + } + +}
\ No newline at end of file |
