根據Spring Data REST Documentation,POST方法會根據給定的請求主體創建一個新的實體。但是,我發現它也可以更新現有的實體。在某些情況下,這可能會有問題。這裏有一個例子:春季數據REST中不會導致PK衝突的POST重複條目
DemoApplication.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
UserRepository.java
package com.example;
import org.springframework.data.repository.PagingAndSortingRepository;
public interface UserRepository extends PagingAndSortingRepository<User, String> {}
User.java
package com.example;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class User {
@Id
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
的pom.xml(內項目標籤)
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
個
application.properties:空
URL:http://localhost:8080/users
方法:POST
JSON內容:
{"username":"user","password":"password"}
我假定上述POST請求被在第一時間獲取HTTP 201 ,只有一次。但是,我能夠多次發送上述POST請求,並始終獲得HTTP 201。另外,我還可以使用POST請求更改數據庫中的密碼。
我認爲這是一個安全問題。例如,我可能允許通過POST請求進行匿名用戶註冊。但是,在上述情況下,現有用戶可能會被覆蓋。
問:我如何防止POST請求創建一個新的實體,如果舊的實體已經用相同的ID存在?或者,我是否錯過了解釋Spring Data REST文檔?
補充說明:
這個問題的原因是Spring背後的數據REST設計。因爲Spring Data REST是建立在Spring Data JPA的基礎上的,而Spring Data JPA並不是用來直接暴露給「外部」的。因此它「信任」數據。org.springframework.data.repository.core.support.AbstractEntityInformation中的方法isNew顯示數據如何確定爲新數據或不新數據。
public boolean isNew(T entity) {
ID id = getId(entity);
Class<ID> idType = getIdType();
if (!idType.isPrimitive()) {
return id == null;
}
if (id instanceof Number) {
return ((Number) id).longValue() == 0L;
}
throw new IllegalArgumentException(String.format("Unsupported primitive id type %s!", idType));
}
isNew方法的結果最終會影響org.springframework.data.jpa.repository.support.SimpleJpaRepository中的存儲方法。
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
在這個問題中提及的情況下,用戶名字段,這也是用戶實體的ID,將始終包含以創建新的用戶數據。因此,當它進入isNew時,id == null將始終返回false。然後,save方法將始終執行合併操作。
上述提示是我所能提供的。儘管如此,我不知道是否有解決方案來解決這個問題。
URL鏈接只是參考。它們可能與我使用的不完全相同。
即使它不是PK/ID,在添加/編輯之前仍需要驗證才能捕獲重複項。對?所以寫一個驗證器。 http://www.baeldung.com/spring-data-rest-validators –