簡體   English   中英

如何使用 Spring Boot 使用 LDAP 登錄從數據庫中獲取用戶角色

[英]How to fetch user role from DB using LDAP login using Spring Boot

嗨,我是 Spring Boot 和 LDAP 的新手。 我面臨問題!

我可以通過 LDAP 登錄,但我無法獲取存儲在我的數據庫中的用戶角色。 我確實收到以下錯誤:

org.springframework.security.ldap.userdetails.LdapUserDetailsImpl cannot be cast to com.test.rnd.geo.web.dto.CustomUser

我試過這個:

    private CustomUser getUserDetails() {
        CustomUser userDetails = (CustomUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        LOGGER.info("Deatils:  "+userDetails);
        LOGGER.info("UserName: " + userDetails.getUsername());
        LOGGER.info("Auth Token: " + userDetails.getAuthToken());
        LOGGER.info("User Role size: " + userDetails.getAuthorities().size());
        LOGGER.info("User Role : " + userDetails.getAuthorities());


        return userDetails;
    }

獲取此 getUserDetails() 函數時出現錯誤。

        CustomUser customUser = getUserDetails();

這是我的 CustomUser 類:

@Component
@Scope("session")
public class CustomUser implements UserDetails {


    private String username;
    private String password;
    private List<RoleEntity> authorities;
    private String authToken;

    public String getAuthToken() {
        return authToken;
    }

    public void setAuthToken(String authToken) {
        this.authToken = authToken;
    }

    public void setAuthorities(List<RoleEntity> authorities) {
        this.authorities = authorities;
    }



    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }

    public void setUsername(String username) {
        this.username = username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "CustomUser{" +
                "username='" + username + '\'' +
                ", password='****" + '\'' +
                ", authorities=" + authorities +
                ", AuthToken='" + authToken + '\'' +
                '}';
    }
}

這是我的 WebSecurityConfig:

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        auth
                .authenticationProvider(customAuthenticationProvider)
                .ldapAuthentication()
                .userSearchFilter("(&(mail={0})(memberOf=CN=aa,OU=Security Group,OU=aa,DC=aa,DC=com))")
                .contextSource()
                .url("ldap://www.domain.com:3268/dc=v,dc=com")
                .managerDn("aaa")
                .managerPassword("aaa");

    }

存儲庫類:

@Repository
public class UserAuthRepository {
    @Autowired
    private InterServiceConnector serviceConnector;
    @Autowired
    private httpsServiceConnector httpsServiceConnector;
    private static final org.slf4j.Logger LOG
            = LoggerFactory.getLogger(CustomAuthenticationProvider.class);


    @Value("${dmzAddress}")
    private String host;

    public CustomUser authenticateUser(String userName, String password) {
        CustomUser customUser = null;
        try {
            customUser = null;

            LOG.info("UserAuthRepository::authenticateUser:: userName" + userName);
//            LOG.info("UserAuthRepository::authenticateUser:: password ********");

            Request request = new Request();
            request.setUsername(userName);
            request.setPassword(password);

            Gson gson = new GsonBuilder().create();
            String jsonInput = gson.toJson(request);

//            LOG.info("UserAuthRepository::authenticateUser:: Authentication Token :: " + request.getAuthToken());

            String user = null;
            if (host.contains("http://")){
                user = serviceConnector.serviceCall(jsonInput, "portalLogin", "post", request.getAuthToken());
            }
            else{
                user = httpsServiceConnector.serviceCall(jsonInput, "portalLogin", "post");
            }
//            String user = serviceConnector.serviceCall(jsonInput, "portalLogin", "post", request.getAuthToken());
//          String user = httpsServiceConnector.serviceCall(jsonInput, "portalLogin", "post");
//            LOG.info("UserAuthRepository::authenticateUser:: user---->>>  " +  user);
            customUser = gson.fromJson(user, CustomUser.class);
            LOG.info("UserAuthRepository:: Custom User::  {}", customUser);
        } catch (JsonSyntaxException e) {
            LOG.error("UserAuthRepository :: authenticateUser :: Parse Exception", e);
        }
        return customUser;
    }



}

首先,您的 CustomUser 應該實現LdapUserDetails而不是UserDetails

您還需要將LdapUserDetailsMapper子類化,因為 Spring 將調用mapUserFromContext ,您可以在此處從數據庫中獲取所需的任何數據並創建 CustomUser 的實例。

@Component
public class CustomLdapUserDetailsMapper extends LdapUserDetailsMapper {

@Autowired
private IUserRepository userRepository;

@Autowired
private IUserRoleRepository userRoleRepository;

@Override
 public UserDetails mapUserFromContext(DirContextOperations ctx, String   username,
        Collection<? extends GrantedAuthority> authorities) {

 
    User user = userRepository.findOneByUsername(username);
    if (user == null) {
        throw new UsernameNotFoundException("Username not found");
    }
    UserDetails userDetails = super.mapUserFromContext(ctx, username, getAuthorities(user));
   //add a constructor for your CustomUser
    return new CustomUser(user.getEmail(), user.getFullName(),  (LdapUserDetails) userDetails);
}

}
private Set<GrantedAuthority> getAuthorities(User user) {
    Set<GrantedAuthority> authorities = new HashSet<>();

    //populate authorities/user roles from User (db entity) and UserRole entities

    for (UserRole userRole : userRoleRepository.findAllByUserId(user.getId())) {
        authorities.add(new SimpleGrantedAuthority(userRole.getRole.getName()));

    }

    return authorities;
}
}

最后,告訴你的身份驗證提供者使用這個 ldap 映射器類(把它放在你的網絡安全代碼中)

@Autowired
private CustomLdapUserDetailsMapper customLdapUserDetailsMapper;     
.... 

customAuthenticationProvider.setUserDetailsContextMapper(customLdapUserDetailsMapper);

更新:CustomUser 代碼可能看起來像這樣

public class CustomUser implements LdapUserDetails{

private  String email;

private String fullName;

private  String username;

private LdapUserDetails ldapUserDetails;

public CustomUser(String email, String fullName, LdapUserDetails  ldapUserDetails) {
    super();
    
    this.email = email;
    this.fullName = fullName;
    this.ldapUserDetails = ldapUserDetails;
}

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

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


@Override
public String getUsername() {
    return ldapUserDetails.getUsername();
}
//add all the other overrides and getter/setter methods

}

存儲庫類可能看起來像

   public interface IUserRepository extends JpaRepository<User, Integer> {

    public User findOneByUsername(String username);

    public User findOneById(Integer id);

    public User findOneByEmail(String email);

}


public interface IUserRoleRepository extends JpaRepository<UserRole, Integer> {

UserRole findOneByRoleName(String rolename);//role name like admin, user, mod etc

UserRole findOneById(Integer id);//role id
}

@dsp_user 提供了很好的解決方案。

現在根據您的上述代碼,我假設您正在使用您的存儲庫類中的一個函數,該函數將用戶名和密碼作為參數。

做類似的另一個函數,只接受用戶名作為參數。 在您的 CustomLdapUserDetailsMapper 類中調用該函數。

試試這個代碼:

@Component
public class CustomLdapUserDetailsMapper extends LdapUserDetailsMapper {

    @Autowired
    private UserRepository userRepository;


    @Override
    public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {

        CustomUser user = userRepository.authenticationMethod(username);
        if (user == null) {
            throw new UsernameNotFoundException("User is not found!");
        }

        return user;
    }

}

我希望這能解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM