如何使用Spring Boot使用LDAP登录从DB获取用户角色



嗨,我是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;
}

}

@dsp_user给出了很好的解决方案。

现在根据你上面的代码,我假设你在你的Repository类中使用一个函数,它以用户名和密码作为参数。

做一个类似的函数,只接受用户名作为参数。在你的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;
}
}

我希望这能解决问题。

首先,您的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映射器类(把它放在你的web安全代码中)

@Autowired
private CustomLdapUserDetailsMapper customLdapUserDetailsMapper;     
.... 
customAuthenticationProvider.setUserDetailsContextMapper(customLdapUserDetailsMapper);

UPDATE: 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
}

最新更新