【问题标题】:loadUserByUsername execute twice using DaoAuthenticationProviderloadUserByUsername 使用 DaoAuthenticationProvider 执行两次
【发布时间】:2015-06-28 20:20:29
【问题描述】:

我正在使用 DaoAuthenticationProvider 进行身份验证,但是当我提交表单时,super.authenticate(authentication) 调用了两次 loadUserByUsername,它最初会抛出 BadCredentialsException,然后在下次成功登录时

如果我不使用密码编码器,这个过程可以正常工作,但是当我使用它时 loadUserByUsername 方法被调用了两次。

下面是我的代码:

安全配置

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
@Qualifier("authenticationProvider")
AuthenticationProvider authenticationProvider;

@Autowired
@Qualifier("userDetailsService")
UserDetailsService userDetailsService;

@Bean
public PasswordEncoder passwordEncoder() {
    PasswordEncoder encoder = new BCryptPasswordEncoder();
    return encoder;
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
        throws Exception {
    auth.authenticationProvider(authenticationProvider)
    .userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

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

    http.authorizeRequests().antMatchers("/admin/**")
            .access("hasRole('ROLE_ADMIN')").and().formLogin()
            .loginPage("/login").failureUrl("/login?error")
            .usernameParameter("username").passwordParameter("password")
            .and().logout().logoutSuccessUrl("/login?logout").and().csrf()
            .and().exceptionHandling().accessDeniedPage("/403");
}

}

身份验证类

@Component("authenticationProvider")
public class LimitLoginAuthenticationProvider extends DaoAuthenticationProvider {

@Autowired
@Qualifier("userDetailsService")
@Override
public void setUserDetailsService(UserDetailsService userDetailsService) {
    super.setUserDetailsService(userDetailsService);
}

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

    try {
        System.out.println("inside authenticate");
        Authentication auth = super.authenticate(authentication);
        return auth;
    } catch (BadCredentialsException be) {
        System.out.println("First call comes here ");
        throw be;
    } catch (LockedException e) {
        throw e;
    }
}
}

MyUserdetailsS​​ervice 类实现 UserDetailsS​​ervice

@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {

@Autowired
private UserDao userDao;

/* below method is called twice if I am using passwordencoder,
initially authentication fails and then again immediately 
on second call authentication succeed */

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

    com.mkyong.users.model.User user = userDao.findByUserName(username);
    List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole());

    return buildUserForAuthentication(user, authorities);

}

private User buildUserForAuthentication(com.mkyong.users.model.User user, List<GrantedAuthority> authorities) {
     MyUserDetails myUserDetails = new MyUserDetails (user.getUsername(), user.getPassword(), user.isEnabled(), user.isAccountNonExpired(), user.isAccountNonLocked(), user.isCredentialsNonExpired(), user.getEmailId(),authorities);
     return myUserDetails;
}

private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {

    Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();

    // Build user's authorities
    for (UserRole userRole : userRoles) {
        setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
    }

    List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);

    return Result;
}

}

请帮帮我。我相信 SecurityConfig 类需要进行一些更改,但我无法弄清楚。

【问题讨论】:

  • 我可以看看,但你必须把它放在github 上让我看看。可以有很多东西要看。你的XML configuration。你能创建一个示例项目吗?
  • @java_dude。好的,我会把我的项目放在 github 上。
  • @java_dude 是否还有其他地方可以直接复制我的项目并粘贴。 Github 发现有点困难
  • 查看此文档以获取github https://guides.github.com/activities/hello-world/。如果您仍然觉得困难,请将其发送到您的google drive。与public分享并在此处提供链接,我将访问它并将其放在github上。
  • @java_dude 我已经提交了文件,同样的 url 是 link

标签: java spring-mvc spring-security


【解决方案1】:

终于在 java_dude 和 SergeBallesta 的帮助下,我得到了查询的解决方案。

经过大量调试后,我看到当 isPasswordValid 方法在 DaoAuthenticationProvider 类中被调用而不是调用 method 1 时,它是从 org.springframework.security 调用 method 2 .authentication.encoding.PlaintextPasswordEncoder 哪个已被贬值,在第二次调用时,它调用了正确的 isPasswordValid 方法一。

方法一

 public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
                checkSalt(salt);
                return delegate.matches(rawPass, encPass);
            }

方法二

 public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
    String pass1 = encPass + "";

    // Strict delimiters is false because pass2 never persisted anywhere
    // and we want to avoid unnecessary exceptions as a result (the
    // authentication will fail as the encodePassword never allows them)
    String pass2 = mergePasswordAndSalt(rawPass, salt, false);

    if (ignorePasswordCase) {
        // Note: per String javadoc to get correct results for Locale insensitive, use English
        pass1 = pass1.toLowerCase(Locale.ENGLISH);
        pass2 = pass2.toLowerCase(Locale.ENGLISH);
    }
    return PasswordEncoderUtils.equals(pass1,pass2);
}

要正确进行身份验证,只需在您的 SecurityConfig 类中添加以下代码,以及我当前有问题的代码。

@Bean
public DaoAuthenticationProvider authProvider() {
 // LimitLoginAuthenticationProvider is my own class which extends DaoAuthenticationProvider 
    final DaoAuthenticationProvider authProvider = new LimitLoginAuthenticationProvider(); 
    authProvider.setUserDetailsService(userDetailsService);
    authProvider.setPasswordEncoder(passwordEncoder());
    return authProvider;
}

** 并更改此方法代码**

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(authProvider())
 .userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

【讨论】:

    猜你喜欢
    • 2012-09-23
    • 2017-04-27
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    相关资源
    最近更新 更多