Аутентификация LDAP через репозиторий LDAP - PullRequest
1 голос
/ 12 апреля 2020

У меня проблемы с разрешением различных типов кодирования с моего сервера LDAP (который находится в SSHA) и значения проверки подлинности простого текста.

Я использую репозиторий LDAP для извлечения моего сервера LDAP и использовал AuthenticationManager и мою собственную реализацию UserDetailService.

При попытке аутентификации всегда возникает проблема с ошибкой неверных учетных данных.

Как видно из моих кодов ниже;

когда я запрашиваю /auth, у меня есть простой текст username и password. Однако, когда я пытаюсь аутентифицировать его с помощью AuthenticationManager, это дает мне неверные учетные данные. Теперь я знаю, что это имеет отношение к UserDetailService.getPassword() и password, предоставленным в UsernamePasswordAuthenticationToken. Речь идет о другом типе шифрования. В моем LDAP есть {SSHA}, также переведенный в двоичный файл (байты), а кодировщик - Bcrypt и String.

Теперь мой вопрос: как правильно аутентифицировать пароль против пароля, возвращаемого LdapRespository ?

ОБНОВЛЕНИЯ

2020-04-12 17:09:46.655  INFO 6672 --- [nio-8080-exec-1] s.w.s.SantaRestApiSecurityConfiguration  : Raw Password:  jdoe123 | Encoded Password: {SSHA}kMgk3gD4prAa/9m4wsPbuAoGhO7UvH2v6+W0Dg==
2020-04-12 17:09:58.110  INFO 6672 --- [nio-8080-exec-1] s.w.s.SantaRestApiSecurityConfiguration  : Raw Password: {SSHA}kMgk3gD4prAa/9m4wsPbuAoGhO7UvH2v6+W0Dg== matches Encoded Password: {SSHA}k1Pp3NICHbwuxFFdT7zno/iG/NTILZGL = false

Выше логов во время сопоставления пароля в PasswordEncoder. Исходя из этого. он показывает, что Raw Password (введенный пользователем) имеет значение ha sh, отличное от Encoded Password (от сервера ldap).

Я использовал LdapShaPasswordEncoder.encode для ха sh введенный пользователем пароль.

Кроме того, я заметил, что каждый раз, когда я хочу аутентифицироваться (звоните http://locahost: xxxx / auth ), вводимый пользователем пароль ha sh меняет каждый раз. Я думаю, что это нормально, когда хэшируется

Конфигурация безопасности ПРИМЕЧАНИЕ: я разрешаю все конечные точки REST-API на данный момент, я ограничу это позже

@Configuration
@EnableWebSecurity
public class SantaRestApiSecurityConfiguration extends WebSecurityConfigurerAdapter   {

    @Autowired
    AuthService authService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // configure AuthenticationManager so that it knows from where to load
        // user for matching credentials
        // Use BCryptPasswordEncoder
        auth.userDetailsService(authService).passwordEncoder(passwordEncoder());
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // TODO Auto-generated method stub
        http.csrf()
            .disable()
            .authorizeRequests().antMatchers("/*").permitAll();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/*");
    }

    /*
     * i am not sure about this since my LDAP server has 
     * a SSHA password encrpytion
     * 
     * */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

LoginController

@RestController
@RequestMapping("/auth")
public class LoginController {

    public static Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    private AuthenticationManager authManager;

    @PostMapping
    public ResponseEntity<String> login(@RequestBody Map<String, String> credentials) {
        String username = credentials.get("username");
        String password = credentials.get("password");

        authManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));

        return new ResponseEntity<String>("", HttpStatus.OK);
    }
}

Реализация UserDetailService

@Service
public class AuthService implements UserDetailsService {

    public static Logger logger = LoggerFactory.getLogger(AuthService.class);

    @Autowired
    UserLdapRepository ldapRepo;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        UserLdap e = ldapRepo.findByUid(username);
        logger.info("{}",e.toString());

        return new AuthDetails(e.getCn(), 
                               e.getPassword(),
                               e.getUid(), 
                               e.getMail(), 
                               e.getSn(), 
                               Long.toString( e.getUidNumber()));
    }
}

Реализация UserDetails

public class AuthDetails implements UserDetails {

    public static Logger logger = LoggerFactory.getLogger(AuthDetails.class);

    private String username;
    private String password;
    private String email;
    private String uidNumber;
    private String sn;
    private String uid;

    public AuthDetails(String username, String password, String uid, String email,String sn, String uidNumber) {
        this.uid = uid;
        this.password = password;
        this.username = username;
        this.email = email;
        this.sn = sn;
        this.uidNumber = uidNumber;
    }

    /*
     * Here i am not sure how to implement this one to satisfy AuthenticationManager
     *
     *
     **/
    @Override
    public String getPassword() {
        return this.password;
    }

    @Override
    public String getUsername() {
        // TODO Auto-generated method stub
        return this.username;
    }

    // some method to implement

}

1 Ответ

0 голосов
/ 12 апреля 2020

Вы используете BCryptPasswordEncoder, но в LDAP используется шифрование SSHA.

Вам необходимо изменить метод passwordEncoder в классе SantaRestApiSecurityConfiguration

  @Bean
public PasswordEncoder passwordEncoder() {
   return  new LdapShaPasswordEncoder();

}



public Class UserLdap {

    @Attribute(name = "userPassword", type = Type.BINARY)
    private byte[] password;
}

и изменить метод loadUserByUsername

@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        UserLdap e = ldapRepo.findByUid(username);
        logger.info("{}",e.toString());
        String password = "{SSHA}" + new String(e.getPassword());
        return new AuthDetails(e.getCn(), 
                               password,
                               e.getUid(), 
                               e.getMail(), 
                               e.getSn(), 
                               Long.toString( e.getUidNumber()));
    } 
...