0

For instance, if I'm hosting a site where users can upload videos, they should be able to modify the title, description, thumbnail, etc... But what's stopping them from modifying the current views? The upload time? Fields that they should NOT be able to change. Couldn't they use a REST tool like Postman and simply send a custom request in JSON format modifying all of these fields? They could potentially set their views to 999999999 if they wished.

My question: Do I need to add a large number of checks to prevent this? If not, what measures must be taken in order to prevent this from happening?

EDIT

Here's an example with Spring which is what I'm using to build my back end:

 @RequestMapping(value="/modify/{id}", method=RequestMethod.POST)
 public ResponseEntity<String> modifyVideo(UserVideo modifiedVideo) {
     UserVideo originalVideo = videoService.findOne(modifiedVideo.getId());

     //Set the prohibited fields back to their original values (checks)
     modifiedVideo.setTotalViews(originalVideo.getTotalViews);
     ...
     //Map modifiedVideo to originalVideo once all prohibited fields are reset
 }
Jake Miller
  • 2,432
  • 2
  • 24
  • 39
  • Not sure but check if this post can be of any help. http://stackoverflow.com/questions/2443324/best-practice-for-partial-updates-in-a-restful-service – mhasan Sep 18 '16 at 18:03
  • Yes, you must validate the requests. This is the most basic thing if you want to do anything with web applications... – inf3rno Sep 23 '16 at 20:51

2 Answers2

2

Besides ensuring the user is authenticated (asserting that the user is who they claim to be) and authorized (asserting that the user is allowed to perform the action they intend to), you must assert that only the updatable fields are exposed your API. Do not expose all the fields for update if not all the fields can be updated.

DTO is a good way to achieve it, as already mentioned in this answer. DTO stands for Data Transfer Object. And this pattern was created with a very well defined purpose: transfer data to remote interfaces, just like web services.

With a DTO, you can expose only a set of attributes of the persistence entities and this approach will give you full control over the attributes you are receiving when creating or updating a resource.

To avoid the boilerplate code of mapping DTOs to/from persistence entities, you can use mapping frameworks. For instance, have a look at MapStruct, which is annotation based and works as a Maven Annotation Processor.

To give your DTOs better names, have a look at this answer.

Community
  • 1
  • 1
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
0

Resetting all the prohibited fields is going to be very tedious and time consuming, it would be better if your design already provided a way of ensuring fields cannot be tampered with without all that extra code.

In my experience it would be better not to expose the fields you do not want to be tampered with.

A common design would be to have two distinct layers, one with a set of classes used to represent each of the logical services you want on each REST service. The other layer, your core, would expose the full suit of functions you require to achieve all the functions of your site, or perhaps just the video uploading portion. The REST layer classes would only have the fields you want in your incoming request from users (e.g. Name, Description, etc.), you would then map these fields to fields within your core business layer classes which is at your discretion and within your control.

Hope this answers your question.

Code sample:

public class ModifyVideo {
  private String name;
  private String description;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }
}

@RequestMapping(value="/modify/{id}", method=RequestMethod.POST)
 public ResponseEntity<String> modifyVideo(ModifyVideo modifyVideo) {
   try {
     UserVideo userVideo = new UserVideo();
     userVideo.setName(modifyVideo.getName());
     userVideo.setDescription(modifyVideo.getDescription());

     videoService.updateUserVideoMetadata(userVideo);
    } catch (SomeCaughtException e) {
      //log the error
      return new ResponseEntity<Error>(HttpStatus.UNPROCESSABLE_ENTITY);
    }
    return new ResponseEntity<Success>(HttpStatus.OK);
 }
Kelevra
  • 11
  • 5
  • So DTO's essentially? – Jake Miller Sep 18 '16 at 18:10
  • @JakeMiller - yes precisely that. At the corporate I work at we have a separate set of DTOs for our REST Layer and EJBs. The former are specifically made to receive the anticipated POST data from the REST call. So in your case videoId (which I omitted in my post which you'd need), name and description for example. – Kelevra Sep 18 '16 at 18:24