[JAVA] Authenticate 3 or more parameters in JSON format using Spring Security

Introduction

In Spring Security, Form authentication is used by default, and the parameter names are username and `` `password```. If you don't have to be so elaborate, you can reduce the amount of code by using the default authentication mechanism, but recently JSON format authentication is increasing, so how to customize it with Spring Security I tried to find out various things.

Authentication parameters

The parameters for this authentication are as follows.

Parameter name Contents
email mail address
password password
tenantCode Tenant code

procedure

1. Prepare a class to store parameters for authentication

Principal.java


@Getter
@Setter
public class Principal {
  private String email;
  private String tenantCode;
  private String password;
}

2. Prepare a class to store login user information

LoginUser.java


@Getter
@Setter
public class LoginUser extends org.springframework.security.core.userdetails.User{
  private long userId;
  private String userName;
  //Add any other properties you want to keep
}

3. Prepare a filter to preprocess authentication

CustomAuthenticationFilter.java


public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

  @Override
  public Authentication attemptAuthentication(HttpServletRequest request,
      HttpServletResponse response) {

    try {
      Principal principal = new ObjectMapper().readValue(request.getInputStream(),
          Principal.class);

      UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
          principal, null);

      setDetails(request, authRequest);

      return this.getAuthenticationManager().authenticate(authRequest);

    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  protected void successfulAuthentication(HttpServletRequest req,
      HttpServletResponse res,
      FilterChain chain,
      Authentication auth) {

    SecurityContextHolder.getContext().setAuthentication(auth);

  }
}

4. Prepare a class to perform authentication processing

CustomAuthenticationProvider.java


@Configuration
public class CustomAuthenticationProvider implements AuthenticationProvider {

  //User information repository
  @Autowired
  UserRepository userRepository;

  //Tenant information repository
  @Autowired
  TenantRepository tenantRepository;

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    //Get what was passed from the CustomAuthenticationFilter class
    Principal principal = (Principal) authentication.getPrincipal();

    if (principal == null) {
      throw new BadCredentialsException("No credentials");
    }

    //Tenant code valid check
    Tenant tenant = tenantRepository.findByTenantCode(principal.getTenantCode());
    if (tenant == null || tenant.getStatus() == 0) {
      throw new BadCredentialsException("The tenant is invalid");
    }

        //Validity check of user by email address and tenant code
    User user = userRepository.findByEmailAndTenantId(principal.getEmail(), tenant.getId());

    //When user information could not be obtained
    if (user == null) {
      throw new BadCredentialsException("User does not exist");
    }

    if (!new BCryptPasswordEncoder().matches(principal.getPassword(), user.getPassword())) {
      throw new BadCredentialsException("your password is incorrect");
    }

    List<GrantedAuthority> authorityList = new ArrayList<>();

    //Permission processing

        LoginUser loginUser = new LoginUser();
    loginUser.setUserId(user.getId());
    loginUser.setUserName(user.getUserName());

    return new UsernamePasswordAuthenticationToken(loginUser, principal.getPassword(),
        authorityList);
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
  }

}

5. Prepare an inheritance class for `` `WebSecurityConfigurerAdapter```

SecurityConfig.java


@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Autowired
  CustomAuthenticationProvider authenticationProvider;

  @Override
  protected void configure(HttpSecurity http) throws Exception {

    CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
    filter.setRequiresAuthenticationRequestMatcher(
        new AntPathRequestMatcher("<Login URL>", "POST"));
    filter.setAuthenticationManager(authenticationManagerBean());

    http
        .csrf()
        .disable()
        .authorizeRequests()
        .antMatchers("<URL that does not require authentication>")
        .permitAll()
        .anyRequest()
        .authenticated()
        .and()
        .logout()
        .logoutRequestMatcher(
            new AntPathRequestMatcher("<Logout URL>", "POST"))
        .and()
        .addFilter(filter);
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(authenticationProvider);
  }
}

reference

-Implement your own authentication with Spring Security -Customize Spring Security, where and what? Memorandum

Recommended Posts

Authenticate 3 or more parameters in JSON format using Spring Security
Output Spring Boot log in json format
Try using JSON format API in Java
Log output in Json format using lograge / lograge-sql with RubyOnRails
Try using Spring Boot Security
Spring Boot Tutorial Using Spring Security Authentication
[Spring MVC] Implement dynamic parameters included in URL without using Optional (~ Java7)
Settings when calling API using CSRF measures of Spring Security in JMeter
How to bind request parameters in list format with bean property in Spring
Set Spring Security authentication result to JSON
Exists using Specification in Spring Data JPA
File output bean as JSON in spring