Spring Security LDAP module providing comprehensive LDAP authentication and authorization capabilities for enterprise applications
—
Jackson JSON serialization support for Spring Security LDAP classes enabling serialization and deserialization of LDAP user details and authorities.
Jackson module providing serialization support for Spring Security LDAP classes.
/**
* Jackson module that provides serialization support for Spring Security LDAP classes
*/
public class LdapJackson2Module extends SimpleModule {
/**
* Creates the LDAP Jackson module with default configuration
*/
public LdapJackson2Module();
/**
* Sets up the module with mixins for LDAP classes
* @param context the setup context
*/
@Override
public void setupModule(SetupContext context);
}Mixin classes providing JSON serialization configuration for LDAP objects.
/**
* Jackson mixin for LdapUserDetailsImpl serialization
*/
public abstract class LdapUserDetailsImplMixin {
@JsonCreator
LdapUserDetailsImplMixin(@JsonProperty("dn") String dn,
@JsonProperty("username") String username,
@JsonProperty("password") String password,
@JsonProperty("enabled") boolean enabled,
@JsonProperty("accountNonExpired") boolean accountNonExpired,
@JsonProperty("credentialsNonExpired") boolean credentialsNonExpired,
@JsonProperty("accountNonLocked") boolean accountNonLocked,
@JsonProperty("authorities") Collection<? extends GrantedAuthority> authorities);
@JsonIgnore
abstract Attributes getAttributes();
}
/**
* Jackson mixin for Person serialization
*/
public abstract class PersonMixin {
@JsonCreator
PersonMixin(@JsonProperty("dn") String dn,
@JsonProperty("cn") String cn,
@JsonProperty("sn") String sn);
@JsonProperty
abstract String getCn();
@JsonProperty
abstract String getSn();
@JsonProperty
abstract String getDescription();
@JsonProperty
abstract String getTelephoneNumber();
}
/**
* Jackson mixin for InetOrgPerson serialization
*/
public abstract class InetOrgPersonMixin extends PersonMixin {
@JsonCreator
InetOrgPersonMixin(@JsonProperty("dn") String dn,
@JsonProperty("cn") String cn,
@JsonProperty("sn") String sn);
@JsonProperty
abstract String getMail();
@JsonProperty
abstract String getEmployeeNumber();
@JsonProperty
abstract String getDisplayName();
@JsonProperty
abstract String getDepartmentNumber();
@JsonProperty
abstract String getCarLicense();
@JsonProperty
abstract String getHomePhone();
}
/**
* Jackson mixin for LdapAuthority serialization
*/
public abstract class LdapAuthorityMixin {
@JsonCreator
LdapAuthorityMixin(@JsonProperty("role") String role,
@JsonProperty("dn") String dn);
@JsonProperty
abstract String getAuthority();
@JsonProperty
abstract String getDn();
}@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new LdapJackson2Module());
return mapper;
}
}@Service
public class LdapUserSerializationService {
private final ObjectMapper objectMapper;
public LdapUserSerializationService(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
public String serializeUser(LdapUserDetails user) throws JsonProcessingException {
return objectMapper.writeValueAsString(user);
}
public LdapUserDetails deserializeUser(String json) throws JsonProcessingException {
return objectMapper.readValue(json, LdapUserDetailsImpl.class);
}
public String serializePerson(Person person) throws JsonProcessingException {
return objectMapper.writeValueAsString(person);
}
public Person deserializePerson(String json) throws JsonProcessingException {
return objectMapper.readValue(json, Person.class);
}
}@Configuration
@ConditionalOnClass({ObjectMapper.class, LdapUserDetails.class})
public class LdapJacksonAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public LdapJackson2Module ldapJackson2Module() {
return new LdapJackson2Module();
}
@Bean
@Primary
public ObjectMapper ldapObjectMapper(LdapJackson2Module ldapModule) {
return JsonMapper.builder()
.addModule(ldapModule)
.build();
}
}@Configuration
public class CustomLdapSerializationConfig {
@Bean
public ObjectMapper customLdapMapper() {
ObjectMapper mapper = new ObjectMapper();
// Register LDAP module
mapper.registerModule(new LdapJackson2Module());
// Custom configuration
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// Custom mixins for additional classes
mapper.addMixIn(CustomLdapUser.class, CustomLdapUserMixin.class);
return mapper;
}
}
// Example custom mixin
abstract class CustomLdapUserMixin {
@JsonCreator
CustomLdapUserMixin(@JsonProperty("username") String username,
@JsonProperty("department") String department,
@JsonProperty("manager") String manager);
@JsonProperty("dept")
abstract String getDepartment();
@JsonIgnore
abstract String getInternalId();
}@RestController
@RequestMapping("/api/ldap")
public class LdapUserController {
private final LdapUserDetailsService userDetailsService;
private final ObjectMapper objectMapper;
public LdapUserController(LdapUserDetailsService userDetailsService,
ObjectMapper objectMapper) {
this.userDetailsService = userDetailsService;
this.objectMapper = objectMapper;
}
@GetMapping("/users/{username}")
public ResponseEntity<String> getUser(@PathVariable String username) {
try {
UserDetails user = userDetailsService.loadUserByUsername(username);
String json = objectMapper.writeValueAsString(user);
return ResponseEntity.ok(json);
} catch (UsernameNotFoundException e) {
return ResponseEntity.notFound().build();
} catch (JsonProcessingException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
@PostMapping("/users")
public ResponseEntity<Void> createUser(@RequestBody String userJson) {
try {
LdapUserDetails user = objectMapper.readValue(userJson, LdapUserDetailsImpl.class);
// Create user logic here
return ResponseEntity.created(URI.create("/api/ldap/users/" + user.getUsername())).build();
} catch (JsonProcessingException e) {
return ResponseEntity.badRequest().build();
}
}
}@Configuration
@EnableRedisHttpSession
public class SessionConfig {
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
return new GenericJackson2JsonRedisSerializer(ldapObjectMapper());
}
private ObjectMapper ldapObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new LdapJackson2Module());
mapper.activateDefaultTyping(
BasicPolymorphicTypeValidator.builder()
.allowIfSubType(Object.class)
.build(),
ObjectMapper.DefaultTyping.NON_FINAL
);
return mapper;
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-security--spring-security-ldap