提问者:小点点

用户登录时Spring Boot安全自定义消息


我正在尝试在我的Spring启动应用程序中集成Spring安全性。所有工作正常,但如果帐户过期或帐户被锁定,我该如何显示消息?此外,我不想显示基于parm的错误消息,如http://localhost:8080/login?error

这是我当前的代码:login. html

        <div th:if="${param.error}" class="alert alert-danger">
            Invalid username or password.
        </div>


        <h3>Sign in to continue</h3>

        <form th:action="@{/login}" name="loginForm"  method="POST">
            <div class="form-group">
                <label for="userNameInput">Username</label>
                <input type="text" class="form-control" id="userNameInput" name="username" placeholder="Username" />
            </div>
            <div class="form-group">
                <label for="passwordInput">Password</label>
                <input type="password" class="form-control" id="passwordInput"  name="password" placeholder="Password"  />
            </div>

            <button type="submit" class="btn btn-success">Login</button>
        </form>

WebSecurityConfig.java

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private CustomUserDetailsService customUserDetailsService;

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

    http
            .authorizeRequests()
            .antMatchers("/", "/css/**", "/js/**","/login/**").permitAll()
            .anyRequest().authenticated()
            .and().formLogin().loginPage("/login").defaultSuccessUrl("/dashboard")
            .and().logout().logoutSuccessUrl("/");
  }

  @Autowired
  public void configAuthBuilder(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(customUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
  }

}

CustomUserDetailsService.java

@Service
public class CustomUserDetailsService implements UserDetailsService {

@Autowired
UserRepository userRepository;

@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

    //query for user from DB
    User user = userRepository.findByUsername(username);


    if (user == null) {
        throw new UsernameNotFoundException(username);
    }

    Date today = new Date();

    //do check if account expired / suspended / deleted
    Boolean isAcconutExpired = false;
    Boolean status = false;

    if (user.getExpireOn() != null && today.before(user.getExpireOn())) {
        isAcconutExpired = false;
    }


    if(user.getStatus() == 1){
        status = true;
    }

    return new org.springframework.security.core.userdetails.User(user.getUsername(),
            user.getPassword(),
            status,
            !isAcconutExpired,
            true,
            true,
            getAuthorities(user));

}

private List<GrantedAuthority> getAuthorities(User user) {
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    authorities.add(new SimpleGrantedAuthority("USER"));
    return authorities;
   }
}

UserRepository.java

@Repository
public interface UserRepository extends CrudRepository<User, Long> {
  User findByUsername(String username);
}

共1个答案

匿名用户

这条消息有点旧,但我目前面临同样的问题。

因此,首先,您必须创建一个自定义的身份验证提供程序实例,让HideUserNotFoundExceptions传递给控件:

public AuthenticationProvider daoAuthenticationProvider() {
    DaoAuthenticationProvider impl = new DaoAuthenticationProvider();
    impl.setUserDetailsService(customUserDetailsService);
    impl.setPasswordEncoder(new BCryptPasswordEncoder());
    impl.setHideUserNotFoundExceptions(false) ;
    return impl ;
}

此外,您应该在AuthenticationProviderBuilder中添加此提供程序,而不是添加自定义DetailService(添加自定义DetailService将添加其他提供程序):

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(daoAuthenticationProvider());

}

有了这个,您现在可以捕获UserNotFoundException而不是基本的BadCre凭据异常。

因此,仍然需要显示这两个异常的自定义错误消息。SpringSecurity直接抛出Bad凭据异常,并带有基于I18n消息AbstractUserDetailsAuthenticationProvider. bad凭据的错误消息(请参阅此处的Spring Security中的实现):

throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));

过期和账户锁定也是如此。所以我建议你改变你的CustomUserDetailsService.java类,用类似的代码错误来做同样的事情:

if (user == null) {
   throw new UsernameNotFoundException(SpringSecurityMessageSource.getAccessor().getMessage("AbstractUserDetailsAuthenticationProvider.UserUnknown",new Object[] {login},"User is not known"));
}

在此之后,您可以在message.properties中添加以下行:

AbstractUserDetailsAuthenticationProvider.UserUnknown = {0} was not found.
AbstractUserDetailsAuthenticationProvider.badCredentials = Password is bad
AbstractUserDetailsAuthenticationProvider.credentialsExpired = User credentials have expired
AbstractUserDetailsAuthenticationProvider.disabled = User is disabled
AbstractUserDetailsAuthenticationProvider.expired = User account has expired
AbstractUserDetailsAuthenticationProvider.locked = User account is locked

并在login. html中显示错误消息:

            <div class="dialog-row">
                <label th:if="${param.error}" th:text="${session['SPRING_SECURITY_LAST_EXCEPTION'].message}" class="text-center redText">Mot de passe inconnu</label>                   
            </div>