Java Spring Extend Userdetails Example

Posted on January 6, 2018


The UserDetailsService is a core interface in Spring Security framework, which is used to retrieve the user's authentication and authorization information.

It has a single read-only method named as loadUserByUsername() which locate the user based on the username.

This post shows you how to create a custom UserDetailsService for authentication in Spring MVC web application.

Tools and technologies used for this application are -

  • Spring Security 5.0.0.RELEASE
  • Spring MVC 5.0.2.RELEASE
  • Servlet API 3.1.0
  • Java SE 9
  • Maven 3.5.2
  • Eclipse Oxygen.2 Release (4.7.2)
  • Jetty Maven plugin 9.4.8

Project structure

Final project structure of our application will look like as follows.

spring-security-userdetails.png

Related - How to create a web project using maven build tool in eclipse IDE.

Jar dependencies

Openpom.xml file of your maven project and add the following dependencies in it.

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>com.boraji.tutorial.springsecurity</groupId>   <artifactId>spring-security-user-details-service-example</artifactId>   <version>0.0.1-SNAPSHOT</version>   <name>Spring Security - Custom UserDetailsService example</name>   <packaging>war</packaging>   <properties>     <maven.compiler.source>9</maven.compiler.source>     <maven.compiler.target>9</maven.compiler.target>     <failOnMissingWebXml>false</failOnMissingWebXml>   </properties>   <dependencies>     <dependency>       <groupId>org.springframework.security</groupId>       <artifactId>spring-security-web</artifactId>       <version>5.0.0.RELEASE</version>     </dependency>     <dependency>       <groupId>org.springframework.security</groupId>       <artifactId>spring-security-config</artifactId>       <version>5.0.0.RELEASE</version>     </dependency>     <dependency>       <groupId>org.springframework</groupId>       <artifactId>spring-webmvc</artifactId>       <version>5.0.2.RELEASE</version>     </dependency>     <dependency>       <groupId>javax.servlet</groupId>       <artifactId>javax.servlet-api</artifactId>       <version>3.1.0</version>       <scope>provided</scope>     </dependency>     <dependency>       <groupId>javax.servlet.jsp</groupId>       <artifactId>javax.servlet.jsp-api</artifactId>       <version>2.3.1</version>       <scope>provided</scope>     </dependency>     <dependency>       <groupId>javax.servlet.jsp.jstl</groupId>       <artifactId>javax.servlet.jsp.jstl-api</artifactId>       <version>1.2.1</version>     </dependency>     <dependency>       <groupId>taglibs</groupId>       <artifactId>standard</artifactId>       <version>1.1.2</version>     </dependency>   </dependencies>    <build>     <plugins>       <!-- Maven jetty plugin for testing war -->       <plugin>         <groupId>org.eclipse.jetty</groupId>         <artifactId>jetty-maven-plugin</artifactId>         <version>9.4.8.v20171121</version>       </plugin>     </plugins>   </build> </project>          

Creating Custom UserDetailsService

To create a custom user service, you need to implement the UserDetailsService interface and override the loadUserByUsername() method.

CreateUserDetailsServiceImp class undercom.boraji.tutorial.spring.service package as follows.

UserDetailsServiceImp.java

            package com.boraji.tutorial.spring.service;  import org.springframework.security.core.userdetails.User.UserBuilder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;  import com.boraji.tutorial.spring.model.User;  public class UserDetailsServiceImp implements UserDetailsService {   @Override   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {      /*Here we are using dummy data, you need to load user data from      database or other third party application*/     User user = findUserbyUername(username);      UserBuilder builder = null;     if (user != null) {       builder = org.springframework.security.core.userdetails.User.withUsername(username);       builder.password(new BCryptPasswordEncoder().encode(user.getPassword()));       builder.roles(user.getRoles());     } else {       throw new UsernameNotFoundException("User not found.");     }      return builder.build();   }    private User findUserbyUername(String username) {     if(username.equalsIgnoreCase("admin")) {       return new User(username, "admin123", "ADMIN");     }     return null;   } }                      

Next, create User model class undercom.boraji.tutorial.spring.model package as follows.

User.java

            package com.boraji.tutorial.spring.model;  public class User {   private String username;   private String password;   private String[] roles;    public User(String username, String password, String... roles) {     this.username = username;     this.password = password;     this.roles = roles;   }    // Getter and Setter methods }                      

Note :- You can useUser model class to map the user data to a database table etc.

Spring Security configuration

To configure Spring Security in Spring MVC application you need to -

  • Create aspringSecurityFilterChain Servlet Filter for protecting and validating all URLs  by create a@Configuration class.
  • Register thespringSecurityFilterChain filter with war.

Now, create a@Configuration class by extending theWebSecurityConfigurerAdapter class and annotate it with @EnableWebSecurity.

Define your custom UserDetailsService class as a @Bean in web security @Configuration class as follows.

WebSecurityConfig.java

            package com.boraji.tutorial.spring.config;  import org.springframework.context.annotation.Bean; 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.bcrypt.BCryptPasswordEncoder;  import com.boraji.tutorial.spring.service.UserDetailsServiceImp;  @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {    @Bean   public UserDetailsService userDetailsService() {     return new UserDetailsServiceImp();   };      @Bean   public BCryptPasswordEncoder passwordEncoder() {     return new BCryptPasswordEncoder();   };      @Override   protected void configure(AuthenticationManagerBuilder auth) throws Exception {     auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());   }    @Override   protected void configure(HttpSecurity http) throws Exception {     http.authorizeRequests().anyRequest().hasAnyRole("ADMIN", "USER")     .and()     .formLogin()     .and()     .logout().permitAll().logoutSuccessUrl("/login")     .and()     .csrf().disable();   }    }                      

Next, createSecurityWebApplicationInitializer class by extending theAbstractSecurityWebApplicationInitializer to register thespringSecurityFilterChain filter.

SecurityWebApplicationInitializer.java

            package com.boraji.tutorial.spring.config;  import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;  public class SecurityWebApplicationInitializer    extends AbstractSecurityWebApplicationInitializer {  }          

Spring MVC configuration

To enable the Spring MVC in your application, you need to annotate your@Configuration  class with@EnableWebMvc annotation.

In this example, we are using the JSP views.  So create a @Configuration class and override the configureViewResolvers() method to register the JSP view resolver.

Also, you can override the addViewControllers() method to map and render the  default login page generated by Spring Security.

WebConfig.java

            package com.boraji.tutorial.spring.config;  import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;  @Configuration @EnableWebMvc @ComponentScan(basePackages = { "com.boraji.tutorial.spring.controller" }) public class WebConfig implements WebMvcConfigurer {   @Override   public void configureViewResolvers(ViewResolverRegistry registry) {     registry.jsp().prefix("/WEB-INF/views/").suffix(".jsp");   }    @Override   public void addViewControllers(ViewControllerRegistry registry) {     registry.addViewController("/login").setViewName("login");   } }                      

Servlet container Initialization and configuration

In Spring MVC, TheDispatcherServlet needs to be declared and mapped for processing all requests either using java orweb.xmlconfiguration.

In a Servlet 3.0+ environment, you can useAbstractAnnotationConfigDispatcherServletInitializer class to register and initialize theDispatcherServlet programmatically as follows.

MvcWebApplicationInitializer.java

            package com.boraji.tutorial.spring.config;  import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;  public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {    // Load  spring security configuration   @Override   protected Class<?>[] getRootConfigClasses() {     return new Class[] { WebSecurityConfig.class };   }    // Load spring web configuration   @Override   protected Class<?>[] getServletConfigClasses() {     return new Class[] { WebConfig.class };   }    @Override   protected String[] getServletMappings() {     return new String[] { "/" };   }  }                      

Controller class

Create a simple@Controller class undercom.boraji.tutorial.spring.controller package as follows.

MyContoller.java

            package com.boraji.tutorial.spring.controller;  import java.security.Principal;  import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping;  @Controller public class MyContoller {    @GetMapping("/")   public String index(Model model, Principal principal) {     model.addAttribute("message", "You are logged in as " + principal.getName());     return "index";   } }                      

JSP views

Create anindex.jsp file undersrc\main\webapp\WEB-INF\views folder and write the following code in it.

index.jsp

            <%@ page language="java" contentType="text/html; charset=ISO-8859-1" 	pageEncoding="ISO-8859-1"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Spring Security 5</title> </head> <body> <h1>Spring Security - Custom UserDetailsService Example</h1> <h2>${message}</h2>  <form action="/logout" method="post"> 	<input value="Logout" type="submit"> </form> </body> </html>          

Run application

Use the following maven command to run your application.

mvn jetty:run (This command deploy the webapp from its sources, instead of build war).

Enter the http://localhost:8080/ URL in browser's address bar to test our application.

On entering the URL, you will see the login page asking for username and password as follows.

spring-security-userdetails_01.png

On successful login, you will see the index page as follows.

spring-security-userdetails_02.png

bowershalied.blogspot.com

Source: https://www.boraji.com/spring-security-5-custom-userdetailsservice-example

0 Response to "Java Spring Extend Userdetails Example"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel