[JAVA] How to implement authentication process by specifying user name and password in Spring Boot

Introduction

In the Spring Boot authentication process, I investigated how to specify a password that I had been wondering for a long time.

Overview

We will show you how to implement authentication process with user name and password in Spring Boot and Spring Security.

The prerequisite environment is as follows.

Version
Java 1.7
Spring Boot 1.5.9.RELEASE

[Problem] Password cannot be specified in `ʻUserDetailsService``

If you go to "Spring Boot Authentication Process", you will find many samples using loadUserByUsername of `ʻUserDetailsService`` [^ fqcn-uds]. I have also written. → Use Basic authentication with Spring Boot

However, as shown below, the argument of loadUserByUsername is only `ʻusername``.

UserDetailsService


UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;

Therefore, it cannot be handled when ** authentication process with user name and password ** is required. For example, in the following cases, loadUserByUsername cannot be used.

--Password hashing is performed on the DB side [^ cript], and it is necessary to include the password in the SQL parameter value. --Authentication is performed in an external library, and it is necessary to pass a user name and password set to the API.

[^ cript]: PostgreSQL crypt function, etc.

[Solution] Use `ʻAbstractUserDetailsAuthenticationProvider``

Use ʻAbstractUserDetailsAuthenticationProvider`` [^ fqcn-audap] instead of ʻUserDetailsService. Specifically, by creating a Bean of `ʻAuthenticationProvider using` ʻAbstractUserDetailsAuthenticationProvider``, ** authentication process using user name and password ** can be easily implemented.

Sample code

Register Authentication Provider with Java Config


@Configuration
public class MyConfigure extends WebSecurityConfigurerAdapter {
  //* Basic authentication is required for all URLs to check the operation.
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic().realmName("My sample realm"); //Basic authentication settings
    http.authorizeRequests().anyRequest().authenticated(); //Setting requests that require authentication
  }


  // ----------------------------------------
  //Bean definition
  // ----------------------------------------

  @Bean
  public AuthenticationProvider getAuthenticationProvider() {
    //Use your own AuthenticationProvider
    return new MyUserDetailsAuthenticationProvider();
  }
}

Definition of your own Authentication Provider


//By inheriting AbstractUserDetailsAuthenticationProvider, it is OK to implement only retrieveUser
public class MyUserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
  private static final String DUMMY_PASSWORD = "DUMMY_PASSWORD"; //* Since it is not used for authentication, any value can be used.(Null and empty string are NG)
  private static final List<GrantedAuthority> AUTH_USER = AuthorityUtils.createAuthorityList("USER"); //* In this sample, all have this authority.

  // <<< N/A >>>
  @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {}
  //---

  @Override
  protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    String userId = username;
    String password = (String) authentication.getCredentials();

    //Check user ID and password
    boolean isValid = AuthApi.isValidUserIdAndPassword(userId, password); //* Pseudo code that authenticates with the API of the external library
    if (!isValid) { throw new UsernameNotFoundException(username); }

    //Implementation of UserDetails(User)Is generated and used as the return value
    return new User(username, DUMMY_PASSWORD, AUTH_USER);
  }
}

Finally

As I wrote at the beginning, there are a lot of samples using loadUserByUsername, but for some reason there seemed to be few samples using passwords for authentication processing, so I looked it up and wrote it. If you have any mistakes or improvements, please let us know.

Recommended Posts

How to implement authentication process by specifying user name and password in Spring Boot
Implement login function in Rails simply by name and password (1)
Implement login function in Rails simply by name and password (2)
How to call and use API in Java (Spring Boot)
How to add a classpath in Spring Boot
How to bind to property file in Spring Boot
How to create a Spring Boot project in IntelliJ
How to use CommandLineRunner in Spring Batch of Spring Boot
How to boot by environment with Spring Boot of Maven
How to change application.properties settings at boot time in Spring boot
Implement login function simply with name and password in Rails (3)
How to control transactions in Spring Boot without using @Transactional
I don't know which user name and password to enter for user authentication when starting tomcat.
How to give Spring Security authenticated user information other than userId and password and how to refer to it
With Spring boot, password is hashed and member registration & Spring security is used to implement login function.
How to use Lombok in Spring
How to set Spring Boot + PostgreSQL
How to set and use profile in annotation-based Configuration in Spring framework
Implement REST API in Spring Boot
How to make CsrfRequestDataValueProcessor and original RequestDataValueProcessor coexist on Spring Boot
Implement Spring Boot application in Gradle
How to use ModelMapper (Spring boot)
How to name variables in Java
[Ruby on Rails] How to log in with only your name and password using the gem devise
How to display characters entered in Spring Boot on a browser and reference links [Introduction to Spring Boot / For beginners]
[Spring Boot] I investigated how to implement post-processing of the received request.
How to implement a slideshow using slick in Rails (one by one & multiple by one)
[Rails] How to log in with a name by adding a devise name column
[Spring Boot Actuator] How to manually register your own health check process
How to update user edits in Rails Devise without entering a password
How to not start Flyway when running unit tests in Spring Boot
How to implement the email authentication function at the time of user registration
How to implement search functionality in Rails
How to implement date calculation in Java
How to implement Kalman filter in Java
How to change app name in rails
How to include Spring Tool in Eclipse 4.6.3?
How to implement coding conventions in Java
How to implement ranking functionality in Rails
How to implement asynchronous processing in Outsystems
How to split Spring Boot message file
Add spring boot and gradle to eclipse
[Spring Boot] How to get properties dynamically from a string contained in a URL
Get the class name and method name of Controller executed by HandlerInterceptor of Spring Boot
How to set environment variables in the properties file of Spring boot application
How to use MyBatis2 (iBatis) with Spring Boot 1.4 (Spring 4)
How to use built-in h2db with spring boot
Output request and response log in Spring Boot
How to make Spring Boot Docker Image smaller
How to use Spring Boot session attributes (@SessionAttributes)
Try to implement login function with Spring Boot
How to separate .scss by controller in Rails
How to implement a like feature in Rails
How to implement optimistic locking in REST API
How to define multiple orm.xml in Spring4, JPA2.1
[Spring Boot] How to refer to the property file
[Introduction to Spring Boot] Authentication function with Spring Security
Spring Boot --How to set session timeout time
How to implement Pagination in GraphQL (for ruby)
Until you create a Spring Boot project in Intellij and push it to Github
[Java] How to get the key and value stored in Map by iterative processing