Skip to content

Commit

Permalink
Custom user details service with a registration page
Browse files Browse the repository at this point in the history
  • Loading branch information
theEmperorofDaiViet committed Nov 30, 2022
1 parent 3266c90 commit 996a81c
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 17 deletions.
68 changes: 68 additions & 0 deletions src/main/java/tacos/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package tacos;

import java.util.Arrays;
import java.util.Collection;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;

@Entity
@Data
@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
@RequiredArgsConstructor
@Table(name="RegisteredUsers")
public class User implements UserDetails{

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;

private final String username;
private final String password;
private final String fullname;
private final String street;
private final String city;
private final String state;
private final String zip;
private final String phoneNumber;

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}

}
11 changes: 11 additions & 0 deletions src/main/java/tacos/data/UserRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package tacos.data;

import org.springframework.data.repository.CrudRepository;

import tacos.User;

public interface UserRepository extends CrudRepository<User, Long>{

User findByUsername(String username);

}
35 changes: 35 additions & 0 deletions src/main/java/tacos/security/RegistrationController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package tacos.security;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import tacos.data.UserRepository;

@Controller
@RequestMapping("/register")
public class RegistrationController {

private UserRepository userRepo;
private PasswordEncoder passwordEncoder;

public RegistrationController(UserRepository userRepo, PasswordEncoder passwordEncoder) {
this.userRepo = userRepo;
this.passwordEncoder = passwordEncoder;
}

@GetMapping
public String registerForm() {
return "registration";
}

@PostMapping
public String processingRegistration(RegistrationForm form) {
userRepo.save(form.toUser(passwordEncoder));
return "redirect:/login";

}

}
26 changes: 26 additions & 0 deletions src/main/java/tacos/security/RegistrationForm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package tacos.security;

import org.springframework.security.crypto.password.PasswordEncoder;

import lombok.Data;
import tacos.User;

@Data
public class RegistrationForm {

private String username;
private String password;
private String fullname;
private String street;
private String city;
private String state;
private String zip;
private String phone;

public User toUser(PasswordEncoder passwordEncoder) {
return new User(
username, passwordEncoder.encode(password),
fullname, street, city, state, zip, phone);
}

}
27 changes: 13 additions & 14 deletions src/main/java/tacos/security/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

Expand All @@ -18,28 +20,25 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter{

@Autowired
DataSource dataSource;

@Autowired
private UserDetailsService userDetailService;

@Bean
public PasswordEncoder encoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
auth.ldapAuthentication()
.userSearchBase("ou=people")
.userSearchFilter("(uid={0})")
.groupSearchBase("ou=roles")
.groupSearchFilter("member={0}")
.passwordCompare()
.passwordEncoder(encoder)
.passwordAttribute("userPassword")
.and()
.contextSource()
.root("dc=tacocloud2,dc=com")
.ldif("classpath:users.ldif");
auth.userDetailsService(userDetailService)
.passwordEncoder(encoder());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/design", "/orders").permitAll()
.antMatchers("/design", "/orders").hasRole("USER")
.antMatchers("/", "/**").permitAll()
.and()
.formLogin().loginPage("/login")
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/tacos/security/UserRepositoryUserDetailsService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package tacos.security;

import org.springframework.beans.factory.annotation.Autowired;
import tacos.User;
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 tacos.data.UserRepository;

@Service
public class UserRepositoryUserDetailsService implements UserDetailsService{

private UserRepository userRepo;

@Autowired
public UserRepositoryUserDetailsService(UserRepository userRepo) {
this.userRepo = userRepo;
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepo.findByUsername(username);
if(user != null) {
return user;
}
throw new UsernameNotFoundException("User '" + username + "' not found");
}

}
4 changes: 3 additions & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ spring.datasource.password=05012001
#spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.database-platform=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
43 changes: 43 additions & 0 deletions src/main/resources/templates/registration.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>Taco Cloud</title>
</head>

<body>
<h1>Register</h1>
<img th:src="@{/images/TacoCloud.png}"/>

<form method="POST" th:action="@{/register}" id="registerForm">
<label for="username">Username: </label>
<input type="text" name="username"/><br/>

<label for="password">Password: </label>
<input type="password" name="password"/><br/>

<label for="confirm">Confirm password: </label>
<input type="password" name="confirm"/><br/>

<label for="fullname">Full name: </label>
<input type="text" name="fullname"/><br/>

<label for="street">Street: </label>
<input type="text" name="street"/><br/>

<label for="city">City: </label>
<input type="text" name="city"/><br/>

<label for="state">State: </label>
<input type="text" name="state"/><br/>

<label for="zip">Zip: </label>
<input type="text" name="zip"/><br/>

<label for="phone">Phone: </label>
<input type="text" name="phone"/><br/>

<input type="submit" value="Register"/>
</form>
</body>
</html>
4 changes: 2 additions & 2 deletions src/main/resources/users.ldif
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ sn: Marmeladova
uid: sonya
userPassword: {noop}marmeladova

dn: cn=ROLE_USER,ou=roles,dc=tacocloud2,dc=com
dn: cn=USER,ou=roles,dc=tacocloud2,dc=com
objectclass: top
objectclass: groupOfUniqueNames
cn: ROLE_USER
cn: USER
ou: user
uniqueMember: uid=sonya,ou=people,dc=tacocloud2,dc=com

0 comments on commit 996a81c

Please sign in to comment.