0

We have a concern exposing internal IDs to the outside world. Therefore I'm thinking about using a hashing mechanism (current choice is hashids) to hash our IDs.

I tried to use a @JsonSerializer and @JsonDeserializer mapping on the Entities ID field. But this only takes effect when including the ID in the body, and has no impact on the IDs in the URL paths.

Is there a possibility to do this, e.g. something like an ID Translation SPI?

Christoph
  • 5
  • 3

3 Answers3

0

The only thing I can think of is to create a request filter that would take the request with encoded ID in URL, then decode the ID and redirect to an URL with decoded ID.

Konrad Botor
  • 4,765
  • 1
  • 16
  • 26
  • Yes, that would resolve the issue with the IDs in the URL, but doesn't change the HATEOS links in the body. – Christoph Jun 25 '18 at 07:12
  • I guess you would have to edit your response in the filter too, something like [this](https://stackoverflow.com/questions/14736328/looking-for-an-example-for-inserting-content-into-the-response-using-a-servlet-f) – Konrad Botor Jun 25 '18 at 07:37
0

What you need is working "right from the box" in Spring Data REST by customizing item resource URIs:

@Configuration
public class RestConfigurer extends RepositoryRestConfigurerAdapter {

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.withEntityLookup().forRepository(ModelRepo.class, model -> HashIdUtil.encode(model.getId()), ModelRepo::findByEncodedId);
        super.configureRepositoryRestConfiguration(config);
    }
}
public interface ModelRepo extends JpaRepository<Model, Long> {

    default Model findByEncodedId(String encodedId) {
        return getById(HashIdUtil.decode(encodedId));
    }

    Model getById(Long id);
}
public class HashIdUtil {

    private static final Hashids HASHIDS = new Hashids("salt", 8);

    public static String encode(Long source) {
        return HASHIDS.encode(source);
    }

    public static Long decode(String source) {
        return HASHIDS.decode(source)[0];
    }
}

Unfortunately, due to the bug (I suppose), PUT/PATCH-ing entities does not work in Spring Boot 2+, unlike the previous version of SB (1.5+) where it works as expected.

See my demo: sdr-hashids-demo

Cepr0
  • 28,144
  • 8
  • 75
  • 101
0

You could try using a converter.

@Component
@AllArgsConstructor
public class HashIdConverter implements Converter<String, Long> {

    private final HashidsUtil hashidsUtil;

    @Override
    public Long convert(@NonNull String source) {
        return hashidsUtil.decodeId(source);
    }
}

Using it the way I just showed you is a bit unsafe, but it can do the work quite well if you are careful enough

Fambo
  • 96
  • 3
  • 5