在春休中,如何覆盖 GET 和 PUT 调用?



我的Spring REST程序是使用Json Web Tokens(JWT(的Stephen Zerhusen演示的轻微扩展,工作正常 - 就目前而言。我添加了一个 Option 对象,我可以使用 Option 类 (@Entity( 和 OptionRepository 接口(扩展 JpaRepository( 进行 GET、PUT 和 POST。

我现在正在尝试将返回的数据限制为登录用户有权访问的数据,但失败了。 例如,假设我的登录用户仅对选项值 1、3 和 5 具有权限。

  • 如果我有像 GET/option 这样的服务调用,我不应该返回 Option 值 2 或 4。
  • 如果我有一个像 GET/option/2 这样的服务调用,我应该得到一个 HTTP 404 结果。

我知道,一旦用户登录,我就可以通过主体对象引用获取他们的用户信息。 在前面的堆栈溢出问题中提供了这样的解决方案,其他页面也提供了类似的解决方案。

我的直接问题是找到我可以影响/option 的 GET 和 PUT 行为的位置。 以下是我添加到现有工作演示中的所有内容。 首先是实体定义类。

@Entity
@Table(name="choice")
public class Option implements Serializable {
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id = Utilities.INVALID_ID;
@Column(name="value", length=50, nullable=false)
private String value;
@Column(name="name", length=100, nullable=false)
private String name;
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
public String getValue() { return this.value; }
public void setValue(String value) { this.value = value; }
public String getName() { return this.name; }
public void setName(String name) { this.name = name; }
}

现在是 JpaRepository 接口扩展:

@RepositoryRestResource(collectionResourceRel="option", path="option")
public interface OptionRepository extends JpaRepository<Option, Long> {
}

我只是将这两个文件添加到程序中以及 GET、PUT 和 POST 工作。顺便说一句,事实证明,如果我注释掉 @RepositoryRestResource 语句,对/option/1 的调用将返回 HTTP 404。 一些文档表明它不需要,但我想它确实是。

现在过滤输出。 让我们假装通过使服务器始终返回 Option (id = 5( 来过滤。 我通过以下方式做到这一点:

@RepositoryRestResource(collectionResourceRel="option", path="option")
public interface OptionRepository extends JpaRepository<Option, Long> {
@RequestMapping(path = "/option/{id}", method = RequestMethod.GET)
@Query("from Option o where o.id = 5")
public Iterable<Option> getById(@PathVariable("id") Long id);
}

当我运行此服务器并执行 GET/option/1 时,我回来了......选项 1,而不是选项 5。不使用@Query。

影响 GET、PUT 等需要什么魔法?

谢谢

杰罗姆。

可以使用资源处理器操作返回的资源:

@Component
public class OptionResourceProcessor implements ResourceProcessor<Resource<Option>> {
@Override
public Resource<Option> process(Resource<Option> resource) {
Option option = resource.getContent();
if (/* Logged User is not allowed to get this Option */ ) {
throw new MyCustomException(...);
} else {
return resource;
}
}
}

然后,您可以创建自定义异常处理程序,例如:

@ControllerAdvice
public class ExceptionsHandler {
@ExceptionHandler(MyCustomException.class)
public ResponseEntity<?> handleMyCustomException(MyCustomException e) {
return new ResponseEntity<>(new MyCustomMessage(e), HttpStatus.FORBIDDEN);
}
}

若要向 PUT/POST/DELETE 请求添加一些逻辑,可以使用自定义事件处理程序,例如:

@RepositoryEventHandler(Option.class) 
public class OptionEventHandler {
@HandleBeforeSave
public void handleBeforeSave(Option option) {
if (/* Logged User is not allowed to save this Option */ ) {
throw new MyCustomException(...);
}   
}
}

您可以在我的示例项目中找到更多 SDR 使用示例...

最新更新