【问题标题】:In Spring Rest, how do I override the GET and PUT calls?在 Spring Rest 中,如何覆盖 GET 和 PUT 调用?
【发布时间】:2017-08-11 03:29:12
【问题描述】:

我的 Spring REST 程序是 Stephen Zerhusen 演示使用 Json Web Tokens (JWT) 的一个小扩展,运行良好——就目前而言。我添加了一个 Option 对象,我可以只使用一个 Option 类 (@Entity) 和一个 OptionRepository 接口(扩展 JpaRepository)来 GET、PUT 和 POST

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

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

我了解,一旦用户登录,我可以通过 Principal 对象引用获取他们的用户信息。 Such a solution was offered in this previous stackoverflow question,其他页面也提供了类似的解决方案。

我的直接问题是找到可以影响 /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 等需要什么魔法?

谢谢,

杰罗姆。

【问题讨论】:

  • 如果它对您有帮助,请不要忘记接受/投票。)

标签: java spring-data-jpa spring-rest


【解决方案1】:

您可以使用Resource Processor 来操作返回的资源:

@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;
        }
    }
}

然后可以创建自定义Exception handler,例如:

@ControllerAdvice
public class ExceptionsHandler {

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

要为 PUT/POST/DELETE 请求添加一些逻辑,您可以使用自定义 Event Handler,例如:

@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(...);
        }   
    }
}

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

【讨论】:

    猜你喜欢
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-11
    • 2021-05-15
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    相关资源
    最近更新 更多