Skip to content

Obfuscated Ids

Sequential numeric ids leak information: how many customers you have, how fast you grow, and they invite enumeration. commons-rest-hashids exposes your Long ids as short opaque strings (e.g. gY6Nl0Vx) using the hashids algorithm — reversible server-side, meaningless to clients.

<dependency>
<groupId>io.rocketbase.commons</groupId>
<artifactId>commons-rest-hashids</artifactId>
<version>4.0.0-M2</version>
</dependency>

The auto-configuration registers everything: an IdObfuscator bean, a Spring MVC formatter for ObfuscatedId parameters, a Jackson deserializer for JSON bodies and an exception handler mapping invalid ids to 404.

hashids:
salt: your-project-secret

The Read DTO exposes ObfuscatedId instead of Long — it serializes to the obfuscated string automatically:

public class CustomerRead {
private ObfuscatedId id; // → "id": "gY6Nl0Vx"
private String name;
}

Producing the id in your converter, via the injected IdObfuscator:

@Component
@RequiredArgsConstructor
public class CustomerConverter
implements EntityReadWriteConverter<CustomerEntity, CustomerRead, CustomerWrite> {
private final IdObfuscator idObfuscator;
@Override
public CustomerRead fromEntity(CustomerEntity entity) {
return CustomerRead.builder()
.id(idObfuscator.obfuscate(entity.getId()))
.name(entity.getName())
.build();
}
// ...
}

Path variables and request params are decoded transparently — just type them as ObfuscatedId:

@GetMapping("/api/customer/{id}")
public CustomerRead getById(@PathVariable ObfuscatedId id) {
return converter.fromEntity(repository.findById(id.getId()) // the real Long
.orElseThrow(NotFoundException::new));
}

An undecodable string (tampered, wrong salt) raises ObfuscatedDecodeException, which the bundled handler renders as 404 – invalid id. JSON body fields of type ObfuscatedId are decoded the same way.

Property Default Explanation
hashids.salt (empty) salt for hashids — set this
hashids.minHashLength 8 minimum length of the generated hash
hashids.alphabet abcdefghijklmnopqrstuvwxyz1234567890 encoding alphabet (uppercase skipped by default)
hashids.invalid.allowed false when true, invalid input is injected as ObfuscatedId with the raw text but id = null instead of a 404
hashids.handler.enabled true toggle the 404 exception handler