Spring Security LDAP-аутентификация и сбор сведений о пользователе из локальной базы данных - PullRequest
0 голосов
/ 24 октября 2018

Таким образом, пользователь проходит аутентификацию, но я, кажется, действительно вошел в учетную запись пользователя.

В настоящее время я работаю над реализацией аутентификации LDAP в проекте.Похоже, что часть аутентификации работает в том смысле, что мое приложение принимает правильные учетные данные.Проблема, с которой я столкнулся, заключается в том, что я не могу получить доступ к «принципалу» в моих представлениях jsp.(Я смог получить доступ ко всему этому, прежде чем перейти на LDAP).При выполнении трассировки моя служба CustomUserDetails запрашивает и запрашивает правильную информацию об учетной записи.Любая помощь приветствуется

Это будет отображать правильное имя пользователя:

<sec:authorize access="isAuthenticated()">
   <h2><sec:authentication property="name"/></h2>
</sec:authorize>

Это не (это работало до LDAP)

<sec:authorize access="isAuthenticated()">
   <h2><sec:authentication property="principal.firstName"/></h2>
</sec:authorize>

Соответствующий код SecurityConfig.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.ldap.authentication.UserDetailsServiceLdapAuthoritiesPopulator;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Bean
    public CustomSaltSource customSaltSource(){ return new CustomSaltSource();}

    @Bean
    public AuthenticationSuccessHandler myAuthenticationSuccessHandler(){
        return new AuthenticationSuccessHandler();
    }



    @Autowired
    void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.ldapAuthentication().contextSource()
                .url("ldap://bar.foo.com")
                .port(####)
                .and()
                .userDnPatterns("cn={0},cn=users,dc=ms,dc=ds,dc=foo,dc=com")
                .ldapAuthoritiesPopulator(new UserDetailsServiceLdapAuthoritiesPopulator(userDetailsService));
    }

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

        http.authorizeRequests()
                .antMatchers("/skins/**", "/css/**", "/**/laggingComponents", "/assets/**").permitAll().and()
                .formLogin().loginPage("/login").permitAll().defaultSuccessUrl("/", true).successHandler(myAuthenticationSuccessHandler())
                .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).deleteCookies("JSESSIONID").permitAll()
                .and().authorizeRequests().antMatchers("/api/**").anonymous()
                .and().authorizeRequests().anyRequest().authenticated().and().rememberMe().key("KEY").userDetailsService(userDetailsService);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
        handler.setPermissionEvaluator(new PermissionEvaluator());
        web.expressionHandler(handler);
        web.ignoring().antMatchers( "/skins/**", "/css/**", "/api/**", "/assets/**", "/health"); //"/**/test/**"
    }
}

CustomUserDetaulsService.java

import org.hibernate.Session;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Set;

@Service
public class CustomUserDetailsService implements UserDetailsService{

    @Override
    public CustomUserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
        Session session = DBFactory.factory.openSession();
        User user = (User) session.createQuery("from User where userName =:userName")
                .setParameter("userName", username).uniqueResult();
        if(user == null){
            throw new UsernameNotFoundException("User Not Found");
        }
        //Needed to initialize permissions
        Set<Role> roles = user.getRoles();
        int i = roles.size();
        for(Role role: roles){
            int j = role.getPermissions().size();
        }
        CustomUserDetails userDetails = new CustomUserDetails(user);

        session.close();
        return userDetails;
    }


}

1 Ответ

0 голосов
/ 22 января 2019

Если я не ошибаюсь, вы переключились на авторизацию Ldap, установили шаблоны URL и DN, но по-прежнему предоставляете userDetailsService, который ищет пользователя в базе данных.Вам необходимо установить UserDetailsContextMapper , реализовав интерфейс и создав свой собственный.Это отобразит данные из контекста каталога ldap в ваш пользовательский UserDetails и вернет их с помощью метода mapUserFromContext .

Вот пример CustomUserDetailsContextMapper :

public class CustomUserDetailsContextMapper implements UserDetailsContextMapper {


    private LdapUser ldapUser = null;
    private String commonName;

    @Override
    public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
        Attributes attributes = ctx.getAttributes();
        UserDetails ldapUserDetails = (UserDetails) super.mapUserFromContext(ctx,username,authorities);
        try {
            commonName = attributes.get("cn").get().toString();
        } catch (NamingException e) {
            e.printStackTrace();
        }
        ldapUser = new LdapUser(ldapUserDetails);
        ldapUser.setCommonName(commonName);
        return ldapUser;
    }

    @Override
    public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {

    }
}

Мой пользовательский LdapUser :

public class LdapUser implements UserDetails
{
    private String commonName;
    private UserDetails ldapUserDetails;

    public LdapUser(LdapUserDetails ldapUserDetails) {
        this.ldapUserDetails = ldapUserDetails;
    }

    @Override
    public String getDn() {
        return ldapUserDetails.getDn();
    }

    @Override
    public void eraseCredentials() {

    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return ldapUserDetails.getAuthorities();
    }

    @Override
    public String getPassword() {
        return ldapUserDetails.getPassword();
    }

    @Override
    public String getUsername() {
        return ldapUserDetails.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return ldapUserDetails.isAccountNonExpired();
    }

    @Override
    public boolean isAccountNonLocked() {
        return ldapUserDetails.isAccountNonLocked();
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return ldapUserDetails.isCredentialsNonExpired();
    }

    @Override
    public boolean isEnabled() {
        return ldapUserDetails.isEnabled();
    }
}

Затем установите CustomUserDetailsContextMapper в конфигурации авторизации.Вот как вы сможете получить своего пользователя из authentication.getPrincipal () .Надеюсь я правильно понял вашу проблему и ответил.

...