【问题标题】:Spring CrudRepository save() doesn't POST, as it thinks its parameter is nullSpring CrudRepository save() 不发布,因为它认为它的参数为空
【发布时间】:2018-02-08 03:02:14
【问题描述】:

我正在使用 Spring Rest 4(spring-boot-starter-data-jpa、spring-boot-starter-data-rest、spring-boot-starter-security)并使用 CrudRepository 访问我的组织数据。 GET 和 PUT 工作正常,但我的 POST 不断从浏览器中看到一个空对象。

这里是报告错误的缩略版:

2017-08-30 06:27:00.049 ERROR 1312 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is javax.validation.ConstraintViolationException: Validation failed for classes [com.logicaltiger.exchangeboard.model.Org] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=userId, rootBeanClass=class com.logicaltiger.exchangeboard.model.Org, messageTemplate='{javax.validation.constraints.NotNull.message}'}
    ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=address1, rootBeanClass=class com.logicaltiger.exchangeboard.model.Org, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'}
    ...
] with root cause

javax.validation.ConstraintViolationException: Validation failed for classes [com.logicaltiger.exchangeboard.model.Org] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=userId, rootBeanClass=class com.logicaltiger.exchangeboard.model.Org, messageTemplate='{javax.validation.constraints.NotNull.message}'}
    ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=address1, rootBeanClass=class com.logicaltiger.exchangeboard.model.Org, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'}
    ...
]

以下是浏览器发送的内容的精简版 (Javascript):

$("#OrgPostBtn").click(function() {
    $.ajax({
        url: "/org",
        type: "POST",
        data: JSON.stringify({  provider: true, name: 'Org NEW', address1: 'Address 24',  [SNIP],  userId: 2 }),
        contentType: "application/json; charset=utf-8",
        headers: createAuthorizationTokenHeader(),
        dataType: "json",
        success: function (data, textStatus, jqXHR) {
            console.log("success: data: " + data + ", textStatus: " + textStatus + ", jqXHR: " + jqXHR);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log("error: jqXHR: " + jqXHR + ", textStatus: " + textStatus);
        }
    });
});

这里是存储库:

@RepositoryRestResource(path="org")
public interface OrgRepository extends CrudRepository<Org, Long> {

    @Override
    @PostAuthorize("returnObject.userId == principal.id || hasRole('ROLE_ADMIN')")
    public Org findOne(@Param("id") Long id);

    @Override
    @PostFilter("filterObject.user_id == principal.id || hasRole('ROLE_ADMIN')")
    public Iterable<Org> findAll();

}

这里是 Org 的精简版:

@Entity
@Table(name="org")
public class Org implements Serializable {
    private static final long serialVersionUID = -2808050088097500043L;

    @Id
    @Column(name="id")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id = Utilities.INVALID_ID;

    @Column(name="provider", nullable=false)
    @NotNull
    private boolean provider;

    @Column(name="name", length=100, nullable=false)
    @NotEmpty
    @Size(max=100)
    private String name;

    @Column(name="address1", length=50, nullable=false)
    @NotEmpty
    @Size(max=50)
    private String address1;

    @Column(name="user_id", nullable=false)
    @NotNull
    private Long userId;

    [SNIP]
}

所以我没有对 PUT 或 POST 进行特殊处理,并且 PUT 处理正常。但我的 POST 数据没有被识别。

这实际上是我原始问题的降级版本,@PreAuthorize() 或 @PostAuthorize 从以下位置看到一个空的#entity:

@Override
@SuppressWarnings("unchecked")
@PreAuthorize("#entity.userId == principal.id || hasRole('ROLE_ADMIN')")
public Org save(@Param("entity") Org entity);   

所以...我正在注释保存参数(@Param),或者我根本没有覆盖的保存()。程序认为我正在尝试发布一个空对象。

如何使用 CrudRepository 解决此问题?

提前致谢,

杰罗姆。

【问题讨论】:

  • userId 以字符串形式发布 - 您需要确保使用转换器将其转换为 long。检查日志以确认。修复是使用这种类型的转换器 - stackoverflow.com/questions/22965178/…
  • 您的断言有问题。在 findOne() 上,@PostAuthorize("returnObject.userId == principal.id || hasRole('ROLE_ADMIN')") 工作正常。但请看我的“答案”。

标签: spring-security spring-data-jpa spring-el spring-rest


【解决方案1】:

我已经弄清楚如何为 PUT 和 POST 配置此存储库。在授权后使用returnObject,如下所示:

@RepositoryRestResource(path="org")
public interface OrgRepository extends CrudRepository<Org, Long> {

    @Override
    @PostAuthorize("returnObject.userId == principal.id || hasRole('ROLE_ADMIN')")
    public Org findOne(@Param("id") Long id);

    @Override
    @PostFilter("filterObject.userId == principal.id || hasRole('ROLE_ADMIN')")
    public Iterable<Org> findAll();

    @Override
    @SuppressWarnings("unchecked")
    @PostAuthorize("reutrnObject.userId == principal.id || hasRole('ROLE_ADMIN')")

}

有了这个,我得到: 普通用户只能 PUT 自己的 Org 记录(userId 匹配)。 普通用户可以发布任何内容。 管理员可以 PUT 或 POST 任何内容。

【讨论】:

    猜你喜欢
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 2017-03-09
    • 1970-01-01
    • 2022-07-11
    • 2020-02-09
    • 1970-01-01
    相关资源
    最近更新 更多