gpt4 book ai didi

java - Spring data rest findBy securityCheck 用于嵌套实体

转载 作者:搜寻专家 更新时间:2023-11-01 03:32:10 25 4
gpt4 key购买 nike

我正在为我的 REST 接口(interface)使用 Spring-data-rest,并且我已经在我公开的端点上实现了自定义安全检查。一切正常,但现在我遇到了一些不平凡的场景,我想知道 spring data rest 是否能够解决这个问题。

我有以下模型:

@Entity
public class Cycle {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "unique_cycle_id")
private long id;

@Column(name = "user_id")
private long userId;

...

@OneToMany(cascade = CascadeType.ALL)
@JoinTable(name = "cycles_records", joinColumns = @JoinColumn(name = "unique_cycle_id"),
inverseJoinColumns = @JoinColumn(name = "unique_record_id"))
private List<Record> records;
}

@Entity
public class Record {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "unique_record_id")
private long id;

...
}

获取周期时,我会检查登录用户是否与我的周期实体中的 userId 具有相同的 ID。

我已经像这样实现了 cystom 安全检查:

@Slf4j
@Component
public class SecurityCheck {

public boolean check(Record record, Authentication authentication) {
log.debug("===Security check for record===");
if (record == null || record.getCycle() == null) {
return false;
}

return Long.toString(record.getCycle().getUserId()).equals(authentication.getName());
}

public boolean check(Cycle cycle, Authentication authentication) {
if (cycle == null) {
return false;
}

return Long.toString(cycle.getUserId()).equals(authentication.getName());
}
}

但是现在,我正在尝试对记录实现类似的安全检查。因此,在获取给定周期的记录时,我需要检查周期的 userId 是否与身份验证对象中的 ID 匹配。

我的 RecordRepository 上有以下方法:

@Repository
public interface RecordRepository extends JpaRepository<Record, Long> {

@PreAuthorize("hasRole('ROLE_ADMIN') OR @securityCheck.check(???, authentication)")
Page<Record> findByCycle_Id(@Param("id") Long id, Pageable pageable);
}

是否可以使用我在此 securityCheck 中使用此方法查询的 id 访问循环内的 userId?如果不是,实现此功能的正确 Spring 方法是什么?

抱歉,我的问题不清楚。如果需要进一步解释,请告诉我。

编辑:我通过访问后过滤器中的返回页面找到了快速而肮脏的解决方案。缺点是当返回的数组为空时,我可以访问不属于我登录用户的记录(所以我仍在寻找一些更优雅的解决方案)

@PostAuthorize("hasRole('ROLE_ADMIN') OR @securityCheck.check(returnObject, authentication)")
Page<Record> findByCycle_Id(@Param("id") Long id, Pageable pageable);

public boolean check(Page<Record> page, Authentication authentication) {
log.debug("===Security check for page===");
if (!page.hasContent()) {
return true;
}

long userId = page.getContent().get(0).getCycle().getUserId();

return Long.toString(userId).equals(authentication.getName());
}

最佳答案

如果我没理解错的话...

首先,确保SpEL EvaluationContext extension已启用。

然后做这样的事情:

public interface RecordRepository extends JpaRepository<Record, Long> {

@Query("select r from Record r join r.cycle c where c.id = ?1 and (c.userId = ?#{@RecordRepository.toLong(principal)} or 1 = ?#{hasRole('ROLE_ADMIN') ? 1 : 0})")
Page<Record> findByCycleId(Long id, Pageable pageable);

default Long toLong(String name) {
return Long.valueOf(name);
}
}

我想 principal 包含 userId 的字符串表示,所以在这里我将它转换为 long 然后比较它们......

你也可以查看我的example与此问题相关...

更新

在 SpEL 表达式中尝试使用 T(java.lang.Long).valueOf(principal) 而不是 @RecordRepository.toLong(principal) 并删除 toLong 来自你的 repo 的方法。

关于java - Spring data rest findBy securityCheck 用于嵌套实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47812031/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com