title: spring boot security login return customized error message
body: <p>I'm using <code>Spring Boot Security</code> framework for a web app.  I have an issue about the user <code>login</code>.  I want to customise the error message and send it back to the page, so that I can show the message.  What I mean customised here is, e.g. <code>wrong user name</code> or <code>wrong user password</code>.  What I'm doing is as following:</p>
  
  <p><strong>SecurityConfig:</strong></p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableGlobalMethodSecurity(prePostEnabled = true)
  public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
      private SuccessLoginHandler successLoginHandler() {
          return new SuccessLoginHandler();
      }
  
      @Override
      @Bean
      public UserDetailsService userDetailsService() {
          return new UserDetailService();
      }
  
      @Override
      protected void configure(AuthenticationManagerBuilder auth)
              throws Exception {
          auth.userDetailsService(userDetailsService()).passwordEncoder(new UserPasswordEncoder());
      }
  
      @Bean
      @Override
      protected AuthenticationManager authenticationManager() throws Exception {
          return super.authenticationManager();
      }
  
      @Override
      public void configure(WebSecurity web) throws Exception {
          web.ignoring().antMatchers("/js/**");
          web.ignoring().antMatchers("/img/**");
          web.ignoring().antMatchers("/css/**");
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
  
          http.csrf().disable()
                  .authorizeRequests()
                  .antMatchers("/home","/login").permitAll()
                  .anyRequest().authenticated()
                  .and()
                  .formLogin()
                  .loginPage("/login")
                  .usernameParameter("username")
                  .passwordParameter("password")
                  .successHandler(successLoginHandler())
                  .permitAll()
                  .and()
                  .logout()
                  .permitAll();
  
      }
  }
  </code></pre>
  
  <p><strong>UserDetailService</strong></p>
  
  <pre><code>@Service
  @Scope("singleton")
  class UserDetailService implements UserDetailsService {
  
      private AccountDataService accountDataService;
  
      @Override
      public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
          UserEx user = accountDataService.mGetUserExByMobile(username);
          if (user == null) {
              throw new UsernameNotFoundException("not found");
          }
  
          List&lt;UserGrantedAuthority&gt; authorities = getAuthorities(user.getMobile());
          return new org.springframework.security.core.userdetails.User(user.getMobile(),
                  user.getPassword(), authorities);
      }
  
      private List&lt;UserGrantedAuthority&gt; getAuthorities(String mobile) {
          List&lt;UserGrantedAuthority&gt; authorities = new ArrayList&lt;&gt;();
  
          List&lt;Permission&gt; permissionList = accountDataService.mGetPermissionList(mobile);
  
          for (Permission perm : permissionList) {
              authorities.add(new UserGrantedAuthority(perm.getAuthority()));
          }
          return authorities;
      }
  
      public AccountDataService getAccountDataService() {
          return accountDataService;
      }
  
      @Autowired
      public void setAccountDataService(AccountDataService accountDataService) {
          this.accountDataService = accountDataService;
      }
  }
  </code></pre>
  
  <p><strong>UserGrantedAuthority</strong></p>
  
  <pre><code>public class UserGrantedAuthority implements GrantedAuthority {
  
      private final String authority;
  
      public UserGrantedAuthority(String authority) {
          Assert.hasText(authority, "A granted authority textual representation is required");
          this.authority = authority;
      }
  
      public String getAuthority() {
          return this.authority;
      }
  
  }
  </code></pre>
  
  <p><strong>UserPasswordEncoder</strong></p>
  
  <pre><code>public class UserPasswordEncoder implements PasswordEncoder {
  
      @Override
      public String encode(CharSequence rawPassword) {
          return null;
      }
  
      @Override
      public boolean matches(CharSequence rawPassword, String encodedPassword) {
          try {
              if (encodedPassword.equals(Helper.md5(rawPassword.toString()))) {
                  //Helper.md5 is just a static method to encode the password.
                  return true;
              }
              return false;
          } catch (Exception e) {
              return false;
          }
      }
  }
  </code></pre>
  
  <p><strong>SuccessLoginHandler</strong></p>
  
  <pre><code>@Component
  class SuccessLoginHandler implements AuthenticationSuccessHandler {
  
      @Override
      public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
  
          String password = request.getParameter("password");
  
          // TODO: logic when login success
  
          response.sendRedirect("/index");
      }
  }
  </code></pre>
  
  <p>As you can see, I have created a success handler to handle the event after user successfully login.  I think probably it's similar to create a customised failure handler and set it to <code>failureHandler()</code> in <code>SecurityConfig</code>.  I've tried as following, but I can only redirect the page, I don't know how to send some extra message at the same time.  </p>
  
  <pre><code>public class FailureLoginHandler implements AuthenticationFailureHandler {
  
      @Override
      public void onAuthenticationFailure(
              HttpServletRequest request,
              HttpServletResponse response,
              AuthenticationException e) throws IOException, ServletException {
  
  
          //what to do to send back some message?
  
          response.sendRedirect("/login?error");
  
      }
  }
  </code></pre>
  
  <p>I'm quite new to Spring Boot, any suggestion will be highly appreciated.</p>