针对冲突(409)响应在jparerepository中添加冲突实体



Spring Data REST返回一个409状态码和一个JSON异常体,当一些客户端试图在数据库中POST一个重复的实体。

JpaRepository

@RepositoryRestResource
@PreAuthorize(whoCanPostAndUpdateTheirMessages)
public interface MessageRepository extends JpaRepository<Message, Long> {
}

curl -u $AUTH -X POST -H "Content-Type:application/json" -d '{ "patient": "'$PATIENT_URL'", "date": "2014-01-01T00:00:0", "device": "00:00:00:00:00", "body": "this is a message" }' $SERVER/messages
<<p> 反应/strong>
HTTP/1.1 409 Conflict
{
  "cause" : {
    "cause" : {
      "cause" : null,
      "message" : "ERROR: duplicate key value violates unique constraint "uk_ofdr0s8f4x6q22veekngtwifd"n  Detail: Key (date, device)=(2014-01-01 00:00:00, 00:00:00:00:00) already exists."
    },
    "message" : "could not execute statement"
  },
  "message" : "could not execute statement; SQL [n/a]; constraint [uk_ofdr0s8f4x6q22veekngtwifd]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"

是否可以在响应体中包含冲突实体(ID/URI),以便客户端知道稍后在何处对该资源执行PUT/PATCH ?

我建议返回一个资源uri a location-Header

@RequestMapping(value="/create",method=RequestMethod.GET)
public ResponseEntity<?> create(@Valid Entity purchase ,BindingResult result){
    boolean exits= false;
    // you checks here
    if(exits){
        return ResponseEntity.status(HttpStatus.CONFLICT).header(HttpHeaders.LOCATION, "http://resource/id").build();
    }
    return ResponseEntity.created(new URI("http://resource/id")).build();
}

br

使用服务器端验证方法来检测潜在的冲突(例如,重复的用户名或电子邮件地址),并抛出一个有意义的异常,转换成一个体面的状态码和消息。

一般来说,如果没有必要,不要向客户端透露上下文信息,因为这可能成为攻击者利用的安全风险。

详细信息

我不认为在这里为POST请求返回额外的信息是一个好主意,因为您可能会在尝试创建实体时泄露有关现有实体的敏感信息。

在创建时,所有潜在冲突的属性都应该通过服务器上的专用方法进行验证(即,如果它是Spring Data REST,使用相应的事件和/或验证器),以便您可以实际抛出适当的异常。如果让无效数据流进入数据库,则基本上无法获得有关导致碰撞的其他实体的任何进一步信息。这基本上是在整个应用程序堆栈中传递无效数据的副作用,这本来就不应该发生。

如果调用返回有关现有实体的信息,则可以使用它来窥探该实体的标识符(例如,尝试通过使用已知用户名创建一个实体来查找已经存在的实体的id)。对于PUTPATCH请求,这略有不同,因为客户端首先已经知道发出请求的标识符。

最新更新