Spring Boot Interview Questions

  • Explain the term ‘Spring Boot’.
  • Mention some advantages of Spring Boot
  • How do you create a spring boot project
  • Explain different types of dependency injection.
  • What are the advantages of micro service?
  • What is the default package in Spring Boot?
  • Explain the difference between an embedded container and a WAR.
  • What is the Spring Boot Actuator?
  • What are the embedded containers supported by Spring Boot?
  • How to configure database using Spring Boot?
  • What is a auto-configuration in spring boot?
  • How to disable specific auto-configuration in spring boot?
  • What is the use of YAML in Spring Boot?
  • How to use a profile with Spring Boot?
  • How the ApplicationContext created by Spring Boot?
  • How to access a value defined in the application.properties file in Spring Boot?
  • CORS
  • How to handle exceptions in spring boot?
  • Exception while performing series of update and insert
  • Can you give an example for ReadOnly as true in Transaction management?
  • javax Bean validation? How do you validate bean
  • What are annotations?
  • On which all objects annotations can be applied
  • Annotations in spring boot that you have used

  • 2 Database to a single spring boot application
  • In how many ways we can send and receive data from backend to frontend
  • Spring security
https://www.interviewbit.com/spring-boot-interview-questions/
https://www.javatpoint.com/spring-boot-interview-questions
https://www.baeldung.com/spring-boot-interview-questions
https://www.edureka.co/blog/interview-questions/spring-boot-interview-questions/
https://www.mygreatlearning.com/blog/spring-boot-interview-questions/
https://www.javadevjournal.com/spring-boot/spring-boot-interview-questions/
https://www.marcobehler.com/guides/spring-boot-interview-questions
https://www.guru99.com/spring-boot-interview-questions.html

Java Interview Questions

Core Technical

  • When to use what
    • When do you store data in database? when in source code and when in a properties file example of each
  • Tell me about the project you have been working
    • how is it deployed on server
    • We server, Tomcat, JBOSS and IBM WAS

Practical Question :

  • Design a command prompt in Java
  • Terms and Condition to be displayed
  • How to do you write a text into a file
  • A Registration form if given to you for development. DB Design and Validation Feel free to ask questions and add each and every validation possible
    • First Name and Last Name
    • Age
    • Address

Spring Security with JWT (Symmetric Encryption)

JwtUtil

package com.springSecurity.jwt;

import com.springSecurity.user.UserDetailsServiceImpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class JwtFilter extends OncePerRequestFilter {

	@Autowired
	private JwtUtil jwtUtil;
	@Autowired
	private UserDetailsServiceImpl userDetailsServiceImpl;

	@Override
	protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
			FilterChain filterChain) throws ServletException, IOException {

		String authorizationHeader = httpServletRequest.getHeader("Authorization");

		String token = null;
		String userName = null;

		if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
			token = authorizationHeader.substring(7);
			userName = jwtUtil.extractUsername(token);
		}

		if (userName != null && SecurityContextHolder.getContext().getAuthentication() == null) {

			UserDetails userDetails = userDetailsServiceImpl.loadUserByUsername(userName);

			if (jwtUtil.validateToken(token, userDetails)) {

				UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
						userDetails, null, userDetails.getAuthorities());
				usernamePasswordAuthenticationToken
						.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
				SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
			}
		}
		filterChain.doFilter(httpServletRequest, httpServletResponse);
	}
}

JwtFilter

package com.springSecurity.jwt;

import com.springSecurity.user.UserDetailsServiceImpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class JwtFilter extends OncePerRequestFilter {

	@Autowired
	private JwtUtil jwtUtil;
	@Autowired
	private UserDetailsServiceImpl userDetailsServiceImpl;

	@Override
	protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
			FilterChain filterChain) throws ServletException, IOException {

		String authorizationHeader = httpServletRequest.getHeader("Authorization");

		String token = null;
		String userName = null;

		if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
			token = authorizationHeader.substring(7);
			userName = jwtUtil.extractUsername(token);
		}

		if (userName != null && SecurityContextHolder.getContext().getAuthentication() == null) {

			UserDetails userDetails = userDetailsServiceImpl.loadUserByUsername(userName);

			if (jwtUtil.validateToken(token, userDetails)) {

				UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
						userDetails, null, userDetails.getAuthorities());
				usernamePasswordAuthenticationToken
						.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
				SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
			}
		}
		filterChain.doFilter(httpServletRequest, httpServletResponse);
	}
}

AuthRequest.java

package com.springSecurity.jwt;

public class AuthRequest {
	
	private String userName;
	private String password;
	
	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;
	}	
}

JWTController.java

package com.springSecurity.jwt;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JWTController {
	
	@Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private AuthenticationManager authenticationManager;
	
	@PostMapping("/authenticate")
	public String generateToken(@RequestBody AuthRequest authRequest) throws Exception {
		try {
			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authRequest.getUserName(), authRequest.getPassword()));
		} catch (Exception ex) {
			throw new Exception("inavalid username/password");
		}
		return jwtUtil.generateToken(authRequest.getUserName());
	}
}

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.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.BeanIds;
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.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.springSecurity.jwt.JwtFilter;
import com.springSecurity.user.UserDetailsServiceImpl;

@Configuration
@EnableWebSecurity
@ConditionalOnProperty(name = "myproject.security.enabled", havingValue = "true", matchIfMissing = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	UserDetailsServiceImpl userDetailsServiceImpl;

	@Autowired
	private JwtFilter jwtFilter;

	/**
	 * @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("/authenticate").permitAll().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);

		http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
	}

	@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	@Bean
	DaoAuthenticationProvider authenticationProvider() {
		DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
		daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
		daoAuthenticationProvider.setUserDetailsService(userDetailsServiceImpl);
		return daoAuthenticationProvider;
	}

	@Bean
	PasswordEncoder passwordEncoder() {
		return NoOpPasswordEncoder.getInstance();
//		return new BCryptPasswordEncoder();
	}

}

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;
	}
}

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;
	}
}

UserDetailsImpl.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 UserDetailsImpl implements UserDetails{
	
	private static final long serialVersionUID = 1L;

	private User user;
	
	public UserDetailsImpl(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;
	}
}

UserDetailsServiceImpl.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 UserDetailsServiceImpl implements UserDetailsService{

	@Autowired
	UserDAO userDAO;
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		User user = userDAO.getEmpDetails(username);
		UserDetailsImpl userPrincipal = new UserDetailsImpl(user);
		return userPrincipal;
	}
}

Controller.java

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;
	}
}

App.java

package com.springSecurity;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
(exclude = {org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})
public class App {
	public static void main(String[] args) {
		ApplicationContext applicationContext = SpringApplication.run(App.class, args);
	}
}

Release.sql

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');

Screenshots:

Generating JWT
RequestWithJWT

Reference :

Spring Boot Logging using Logback

  • Just place the logback.xml file in the classpath and it will start working

logback.xml (place in resource folder i.e class path)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<include resource="org/springframework/boot/logging/logback/defaults.xml" />
	<property name="LOG_FILE" value="logs/app.log" />

	<appender name="FILE-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<file>${LOG_FILE}</file>

		<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<fileNamePattern>logs/archived/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
			<!-- each archived file, size max 5KB -->
			<maxFileSize>5KB</maxFileSize>
			<!-- total size of all archive files, if total size > 20KB, it will delete 	old archived file -->
			<totalSizeCap>20KB</totalSizeCap>
			<!-- 60 days to keep -->
			<maxHistory>60</maxHistory>
		</rollingPolicy>

		<encoder>
			<pattern>%d %p %c{1.} [%t] %m%n</pattern>
		</encoder>
	</appender>

	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
		<layout class="ch.qos.logback.classic.PatternLayout">
			<Pattern>
				%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
			</Pattern>
		</layout>
	</appender>


	<logger name="com.dailycodebuffer" level="trace" additivity="false">
		<appender-ref ref="FILE-ROLLING" />
	</logger>

	<root level="error">
		<appender-ref ref="FILE-ROLLING" />
	</root>

	<logger name="com.dailycodebuffer" level="debug" additivity="false">
		<appender-ref ref="CONSOLE" />
	</logger>
	<root level="error">
		<appender-ref ref="CONSOLE" />
	</root>

</configuration>

application.properties

server.port=9191
logging.level.org.springframework=DEBUG
#logging.level.SpringSecurity=DEBUG
#logging.level.root=INFO

logging.pattern.console=%d [%level] %c{1.} [%t] %m%n
logging.file = appLog.log
logging.pattern.file=%d [%level] %c{1.} [%t] %m%n

#[%d] date [%level] i.e info trace etc [%c] = class name [%t] = thread  [%m] = message [%n] new line   

Reference :

Spring Security with DB Authentication

Steps :

  1. Create DB Table that will support your authentication
  2. Create User Bean with all the required fields.
  3. Create a @Repository Bean that creates the User Bean using username
  4. Test step 1 and 2 by directly calling the repository via a controller
  5. Create implementation of UserDetails interface (UserPrincipal) using decorator pattern
  6. Create implementation of UserDetailsService interface (UserPrincipalDetailsService)
  7. Hook the new Authentication provider created into the implementation of WebSecurityConfigurerAdapter class
  8. 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 :

Youtube : Part 1 , Part 2

Code :

GitHub : Branch – spring-security-db-authentication

Enable HTTPS/SSL in SpringBoot

Steps to enable HTTPS :

  1. Generate HTTPS Certificate
    1. Create your own certificate from keytool
    2. Buy the certificate
    3. Generate free certificate from OpenSSL
  2. Make changes in application.properties
  3. Add Bean for ServletWebServerFactory

Generate HTTPS Certificate

Generating certificate using keytool

Add bootsecurity.p12 file into your resource folder of springboot

Make changes in application.properties

application.properties