CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-security--spring-security-ldap

Spring Security LDAP module providing comprehensive LDAP authentication and authorization capabilities for enterprise applications

Pending
Overview
Eval results
Files

json-serialization.mddocs/

JSON Serialization Support

Jackson JSON serialization support for Spring Security LDAP classes enabling serialization and deserialization of LDAP user details and authorities.

Capabilities

LdapJackson2Module

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);
}

Jackson Mixins

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();
}

Usage Examples

Basic Module Registration

@Configuration
public class JacksonConfig {
    
    @Bean
    @Primary
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new LdapJackson2Module());
        return mapper;
    }
}

Serialization Example

@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);
    }
}

Spring Boot Auto-Configuration

@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();
    }
}

Custom Serialization Configuration

@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();
}

REST Controller Integration

@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();
        }
    }
}

Session Serialization

@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

docs

authentication.md

authorities.md

context-management.md

embedded-server.md

index.md

json-serialization.md

password-policy.md

user-details.md

tile.json