Browser Cacheable Signed Image URLs with Spring Boot

Pavith Madusara
2 min readDec 30, 2022

Generating and Server Side Caching Browser Cacheable S3 Pre-Signed URLs for Images.

It is important to note that before implementing the solution described in this article, it is crucial to ensure that it is compatible with your application’s security requirements. Otherwise, this could potentially compromise the security of your application and put sensitive data at risk. This solution is best used in non-sensitive images.

For example, suppose you have a multi-tenant Inventory Management System where you have to store item images in a single S3 bucket. In that case, this solution can be used to create browser cacheable S3 pre-signed URLs.

The basic idea here is to create a long-lasting signed URL with a fixed expiration time and cache it in the server. URL expiration time depends on the project. This way URL will not change for x amount of time so the browser can use the cached images. Also, it is impotent to design this not to affect the update operations. In other words, when we update the image for a related entity, the updated image URL should be sent to the client without any effect from the cache.

Generating Signed URL (This is an Example for AWS S3. Same principal can be applied to any signed URL generation)

We are going to set Expiration time to 00:00:00 at Next Day.

public PreSignedUrlDTO getImagePreSignedUrl(S3EntityDTO entityDTO) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.DATE, 1);
Date expiration = cal.getTime();

return generateSignedUrl(entityDTO, expiration);
}

private PreSignedUrlDTO generateSignedUrl(S3EntityDTO entityDTO, Date expiration) {

log.info("Generating pre-signed URL.");
String key = entityDTO.getKey();
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(bucket, key)
.withMethod(HttpMethod.GET)
.withExpiration(expiration);
URL url = s3.generatePresignedUrl(generatePresignedUrlRequest);

return PreSignedUrlDTO.builder()
.url(url.toString())
.expiration(expiration)
.build();
}

Caching Signed URLs in Server

Because of our expire time configuration, we know that generated Signed URLs will be valid until mid night. So we can cache those URLs and Schedule a Cache Evict at mid night.

If you are using this in a micro service, this caching can be use to reduce lots of internal requests.

@Scheduled(cron = "0 0 0 * * ?")
@CacheEvict(cacheNames = "imageSignedUrl", allEntries = true)
public void evictCache() {
log.info("Evicting cache for imageSignedUrl");
}

@Cacheable(value = "imageSignedUrl", key = "#id")
public PreSignedUrlDTO getImagePreSignedUrl(Long id) {
return getPreSignedUrl(id);
}

That’s It. Make sure to use this approach with application security in mind.

--

--