Steps :
- Create DB Table that will support your authentication
- Create User Bean with all the required fields.
- Create a @Repository Bean that creates the User Bean using username
- Test step 1 and 2 by directly calling the repository via a controller
- Create implementation of UserDetails interface (UserPrincipal) using decorator pattern
- Create implementation of UserDetailsService interface (UserPrincipalDetailsService)
- Hook the new Authentication provider created into the implementation of WebSecurityConfigurerAdapter class
- Test the implementation
- This implementation almost 90% does not work at the first attempt so debug will most effeminately will be required, below points shall help
- Check if the username is getting correctly passed into loadUserByUsername() method
- Check base 64 encoding
- Check the password encoder setting
- Check the logs
- Disable the CSRF
Step 1 : Create DB Table that will support your authentication
create table emp_temp ( EMP_ID number(2), EMP_USERNAME varchar2(10), EMP_PASS varchar2(10), EMP_ROLES varchar2(50), EMP_PERMISSIONS varchar2(50) ); insert into emp_temp values (1,'Tyson','123','ADMIN',''); insert into emp_temp values (2,'Justin','123','USER',''); insert into emp_temp values (3,'Martin','123','ADMIN','MANAGER'); insert into emp_temp values (4,'Jake'',123','USER','MANAGER'); insert into emp_temp values (5,'Duke','123','ADMIN','LEAD'); insert into emp_temp values (6,'Fade'',123','USER','LEAD');

Step 2 : Create User Bean with all the required fields.
User.java
package com.springSecurity.user; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class User { private String id; private String username; private String password; private String roles; private String permissions; public User() { } public User(String id, String username, String password, String roles, String permissions) { this.id = id; this.username = username; this.password = password; this.roles = roles; this.permissions = permissions; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getRoles() { return roles; } public void setRoles(String roles) { this.roles = roles; } public String getPermissions() { return permissions; } public void setPermissions(String permissions) { this.permissions = permissions; } public List<String> getRolesList(){ List<String> arrayList = new ArrayList<>(); if(this.roles.length()>0) { Collections.addAll(arrayList,this.roles.split(",")); } return arrayList; } public List<String> getPermissionsList(){ List<String> arrayList = new ArrayList<>(); if(this.roles.length()>0) { Collections.addAll(arrayList,this.permissions.split(",")); } return arrayList; } }
Step 3 : Create a @Repository Bean that creates the User Bean using username
UserDAO.java
package com.springSecurity.user; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; @Repository public class UserDAO { @Autowired JdbcTemplate jdbcTemplate; public User getEmpDetails(String userName) { StringBuilder query = new StringBuilder(); query.append("select EMP_ID, EMP_USERNAME, EMP_PASS, EMP_ROLES, EMP_PERMISSIONS from emp_temp where EMP_USERNAME=?"); User user =jdbcTemplate.queryForObject(query.toString(),new Object[] {userName}, new RowMapper<User>() { @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { return new User( rs.getString("EMP_ID"), rs.getString("EMP_USERNAME"), rs.getString("EMP_PASS"), rs.getString("EMP_ROLES"), rs.getString("EMP_PERMISSIONS")); } }); return user; } }
Step 4 :Test step 1 and 2 by directly calling the repository via a controller
Controller File
package com.springSecurity; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import com.springSecurity.user.User; import com.springSecurity.user.UserService; @RestController public class DBController { @Autowired JdbcTemplate jdbcTemplate; @Autowired UserService userService; @PostMapping("/empList") public User getEmpList2(@RequestBody Map<String,String> data){ return userService.getEmpDetails(data.get("loginId")); } }
Service File
package com.springSecurity.user; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired UserDAO userDAO; public User getEmpDetails(String userName) { return userDAO.getEmpDetails(userName); } }
Test Using Rest Tool

Step 5 : Create implementation of UserDetails interface (UserPrincipal) using decorator pattern
UserPrincipal.java
package com.springSecurity.user; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; public class UserPrincipal implements UserDetails{ private static final long serialVersionUID = 1L; private User user; public UserPrincipal(User user) { this.user = user; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { List<GrantedAuthority> authorityList = new ArrayList<>(); this.user.getPermissionsList().forEach(p -> { GrantedAuthority authority = new SimpleGrantedAuthority(p); authorityList.add(authority); }); this.user.getRolesList().forEach(p -> { GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_"+p); authorityList.add(authority); }); return authorityList; } @Override public String getPassword() { return user.getPassword(); } @Override public String getUsername() { return user.getUsername(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
Step 6 : Create implementation of UserDetailsService interface (UserPrincipalDetailsService)
UserPrincipalDetailsService.java
package com.springSecurity.user; import org.springframework.beans.factory.annotation.Autowired; 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; @Service public class UserPrincipalDetailsService implements UserDetailsService{ @Autowired UserDAO userDAO; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userDAO.getEmpDetails(username); UserPrincipal userPrincipal = new UserPrincipal(user); return userPrincipal; } }
Step 7 : Hook the new Authentication provider created into the implementation of WebSecurityConfigurerAdapter class
SecurityConfig.java
package com.springSecurity; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 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.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import com.springSecurity.user.UserPrincipalDetailsService; @Configuration @EnableWebSecurity @ConditionalOnProperty (name = "myproject.security.enabled", havingValue = "true", matchIfMissing = true) public class SecurityConfig extends WebSecurityConfigurerAdapter{ @Autowired UserPrincipalDetailsService userPrincipalDetailsService; /**@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("admin1").password(passwordEncoder().encode("admin")).roles("ADMIN").and() .withUser("admin2").password(passwordEncoder().encode("admin")).roles("ADMIN").authorities("MANAGER").and() .withUser("user1").password(passwordEncoder().encode("user")).roles("USER").and() .withUser("user2").password(passwordEncoder().encode("user")).roles("USER").authorities("LEAD"); }*/ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authenticationProvider()); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http .authorizeRequests() .antMatchers("/").permitAll()//bypass authetication and authorization .antMatchers("/empList").permitAll()//bypass authetication and authorization .antMatchers("/empList2").permitAll()//bypass authetication and authorization .antMatchers("/profile").authenticated()//Authentication only required .antMatchers("/user/**").hasRole("USER")//Authetication and Authorization required .antMatchers("/admin/**").hasRole("ADMIN")//Authetication and Authorization required .antMatchers("/useroradmin").hasAnyRole("ADMIN","USER")//Either admin or user role required //permissions .antMatchers("/listTeam").hasAuthority("LEAD")//Authetication, Authorization (since /user/** is required) and permission required .antMatchers("/listEmp").hasAuthority("MANAGER")//Authetication, Authorization and permission required .antMatchers("/**").denyAll() .and() .httpBasic(); http .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); } @Bean DaoAuthenticationProvider authenticationProvider() { DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setPasswordEncoder(passwordEncoder()); daoAuthenticationProvider.setUserDetailsService(userPrincipalDetailsService); return daoAuthenticationProvider; } @Bean PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); // return new BCryptPasswordEncoder(); } }
Step 8 : Test the implementation

Below is the sample controller used for testing
package com.springSecurity; import java.util.ArrayList; import java.util.List; import javax.annotation.security.RolesAllowed; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class Controller { /** * Accessable without Authentication and authorization * @return */ @GetMapping("/") public String getWelcomePage() { return "Hello....welcome to our website"; } /** * All logged in users * Accessable with authentication but authorization not required * @return */ @GetMapping("/profile") public String getProfile() { return "Welcome to profile page"; } /** * Only logged in user with role USER can access this * @return */ @GetMapping("/user") public String getUser() { return "Hello User Role"; } /** * Only loggged in admin can access this * @return */ @GetMapping("/admin") public String getAdmin() { return "Hello Admin Role"; } /** * Either User or Admin * @return */ @GetMapping("/useroradmin") public String getUserOrAdmin() { return "Hello User or Admin Role"; } @GetMapping("/listTeam") public List<String> listTeam() { List<String> list = new ArrayList(); list.add("Team Memeber 1"); list.add("Team Memeber 2"); list.add("Team Memeber 3"); return list; } @GetMapping("/listEmp") public List<String> listEmp() { List<String> list = new ArrayList(); list.add("Team Memeber 1"); list.add("Team Memeber 2"); list.add("Team Memeber 3"); list.add("Team Lead 1"); list.add("Team Lead 2"); return list; } }
Get the UserDetails from the Spring Security using below steps :
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof UserDetails) { username = ((UserDetails)principal).getUsername(); } else { username = principal.toString(); }
Reference :
Code :
GitHub : Branch – spring-security-db-authentication