In
previous post, I explained how to authenticate user via in-memory collection.
In this post, we are going to store user credentials in a database and use them
for authentication purpose.
Step 1:
Create User entity.
@Entity @Table(name = "user") public class User { @Id @Column(name = "user_id") @GeneratedValue private int id; @Column(name = "user_name", nullable = false, unique = true) private String userName; @Column(name = "user_password", nullable = false) private String password; ..... ..... }
Step 2:
Implement
'UserDetails' interface.
public class UserPrincipal implements UserDetails { private static final long serialVersionUID = 1L; private User user; public UserPrincipal(final User user) { super(); this.user = user; } ..... ..... }
Step 3:
Create UserRepository
interface.
public interface UserRepository extends JpaRepository<User, Integer> { User findByUserName(String userName); }
Step 4:
Implement
'UserDetailsService' interface.
@Service public class UserDetailsServiceImpl implements UserDetailsService{ @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUserName(username); if(user == null) { throw new UsernameNotFoundException("User not exist"); } return new UserPrincipal(user); } }
Step 5:
Extend
WebSecurityConfigurerAdapter class and override authenticationProvider and
configure methods.
@Configuration @EnableWebSecurity public class ApplicationSecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsServiceImpl userDetailsService; @Bean public DaoAuthenticationProvider authenticationProvider() { DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setUserDetailsService(userDetailsService); daoAuthenticationProvider.setPasswordEncoder(NoOpPasswordEncoder.getInstance()); return daoAuthenticationProvider; } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.csrf().disable().authorizeRequests().antMatchers("/", "/public/*", "/css/*", "/js/*").permitAll() .anyRequest().authenticated().and().httpBasic(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception{ auth.authenticationProvider(authenticationProvider()); } }
Step 6:
Insert some default
data to user table.
@Bean public CommandLineRunner demo(UserRepository userRepository) { return (args) -> { User user1 = new User(); user1.setUserName("krishna"); user1.setPassword("password123"); User user2 = new User(); user2.setUserName("ram"); user2.setPassword("ram123"); userRepository.saveAll(Arrays.asList(user1, user2)); }; }
Step 7:
Create
application.properties file under 'src/main/resources' and configure it with
jpa settings.
Total
project structure looks like below.
Find the
below working application.
User.java
package com.sample.app.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "user") public class User { @Id @Column(name = "user_id") @GeneratedValue private int id; @Column(name = "user_name", nullable = false, unique = true) private String userName; @Column(name = "user_password", nullable = false) private String password; public int getId() { return id; } public void setId(int 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; } }
UserPrincipal.java
package com.sample.app.model; import java.util.Arrays; import java.util.Collection; 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(final User user) { super(); this.user = user; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { SimpleGrantedAuthority authority1 = new SimpleGrantedAuthority("USER"); SimpleGrantedAuthority authority2 = new SimpleGrantedAuthority("ADMIN"); return Arrays.asList(authority1, authority2); } @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; } }
UserRepository.java
package com.sample.app.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.sample.app.model.User; public interface UserRepository extends JpaRepository<User, Integer> { User findByUserName(String userName); }
UserDetailsServiceImpl.java
package com.sample.app.service; 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; import com.sample.app.model.User; import com.sample.app.model.UserPrincipal; import com.sample.app.repository.UserRepository; @Service public class UserDetailsServiceImpl implements UserDetailsService{ @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUserName(username); if(user == null) { throw new UsernameNotFoundException("User not exist"); } return new UserPrincipal(user); } }
EmployeeController.java
package com.sample.app.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("employees/") public class EmployeeController { @RequestMapping(value = "registered/count", method = RequestMethod.GET) public String countEmps() { return "Total Registered Employees : "+ 1024; } }
HelloWorldController.java
package com.sample.app.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloWorldController { @RequestMapping("/") public String homePage() { return "Welcome to Spring boot Application Development using Spring Security"; } @RequestMapping("/public/aboutme") public String aboutMe() { return "I am securied by spring security module"; } }
ApplicationSecurityConfiguration.java
package com.sample.app.config; import org.springframework.beans.factory.annotation.Autowired; 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.crypto.password.NoOpPasswordEncoder; import com.sample.app.service.UserDetailsServiceImpl; @Configuration @EnableWebSecurity public class ApplicationSecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsServiceImpl userDetailsService; @Bean public DaoAuthenticationProvider authenticationProvider() { DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setUserDetailsService(userDetailsService); daoAuthenticationProvider.setPasswordEncoder(NoOpPasswordEncoder.getInstance()); return daoAuthenticationProvider; } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.csrf().disable().authorizeRequests().antMatchers("/", "/public/*", "/css/*", "/js/*").permitAll() .anyRequest().authenticated().and().httpBasic(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception{ auth.authenticationProvider(authenticationProvider()); } }
App.java
package com.sample.app; import com.sample.app.model.User; import java.util.Arrays; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import com.sample.app.repository.UserRepository; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } @Bean public CommandLineRunner demo(UserRepository userRepository) { return (args) -> { User user1 = new User(); user1.setUserName("krishna"); user1.setPassword("password123"); User user2 = new User(); user2.setUserName("ram"); user2.setPassword("ram123"); userRepository.saveAll(Arrays.asList(user1, user2)); }; } }
application.properties
logging.level.root=WARN logging.level.org.hibernate=ERROR ## H2 specific properties spring.h2.console.enabled=true spring.h2.console.path=/h2 spring.datasource.url=jdbc:h2:file:~/db/myOrg.db;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1; spring.datasource.username=krishna spring.datasource.password=password123 spring.datasource.driverClassName=org.h2.Driver ## JPA specific properties # Creates the schema, destroying previous data. spring.jpa.hibernate.ddl-auto=create spring.jpa.database-platform=org.hibernate.dialect.H2Dialect #spring.jpa.show-sql=true #spring.jpa.properties.hibernate.format_sql=true ## Database connection pooling properties # Number of ms to wait before throwing an exception if no connection is available. spring.datasource.max-wait=10000 # Maximum number of active connections that can be allocated from this pool at the same time. spring.datasource.tomcat.max-active=10 spring.datasource.tomcat.max-idle=5 spring.datasource.tomcat.min-idle=3 spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>springSecurity</groupId> <artifactId>springSecurity</artifactId> <version>1</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> </dependencies> </project>
Run
App.java.
Enter user
name as 'krishna' and password as 'password123' and click on OK button.
You can
see below kind of screen.
You can
download the complete working application from this link.
No comments:
Post a Comment