[英]Spring data rest findBy securityCheck for nested entity
我将Spring-data-rest用于REST接口,并且在暴露的端点上实现了自定义安全检查。 一切正常,但是现在我遇到了一些不平常的情况,我想知道spring数据剩余是否能够解决这个问题。
我有以下模型:
@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;
...
}
在获取周期时,我检查登录用户的ID是否与我的Cycle实体中的userId
相同。
我已经实现了像这样的膀胱囊肿安全检查:
@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扩展 。
然后执行以下操作:
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形式然后进行比较...
您也可以检查我与此问题相关的示例 ...
更新
相反的@RecordRepository.toLong(principal)
在规划环境地政司表达尝试用T(java.lang.Long).valueOf(principal)
,并删除toLong
从您的回购方法。
如果您只需要在检查userId与您登录的用户相同的同时获取“周期”的特定记录,我将使用类似以下内容的方法:
Page<Record> findByCycle_IdAndUserId(Long cycleId, Long userId, Pageable pageable);
JPA本身可以处理很多工作,而无需您手动创建查询。 请参阅https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods中的查询方法。
当然,这意味着安全检查需要在控制器端通过Spring Security而不是模型端进行处理。 您的DAO不必担心请求是否有效/授权,因为这些检查是事先完成的。
干杯
您可以在应用程序中引入两个处理程序,如下所示:-
//This is your Request handler
public class CxfHttpRequestHandler extends AbstractPhaseInterceptor<Message> {
public CxfHttpRequestHandler() {
super("marshal");
}
@Override
public void handleMessage(final Message message) throws Fault {
//handle your all request here
}
}
//this is your Response handler
public class CxfHttpResponseHandler extends AbstractPhaseInterceptor<Message> {
public CxfHttpResponseHandler() {
super("pre-stream");
}
@Override
public void handleMessage(final Message message) throws Fault {
//handle your outgoing message here
}
}
Add the following in your spring-bean.xml file:-
<bean id="cxfHttpRequestHandler" class="com.yourpackage.CxfHttpRequestHandler" >
<description>
This Bean implements Interceptor for all request
</description>
</bean>
<bean id="cxfHttpResponseHandler" class="com.yourpackage.CxfHttpResponseHandler">
<description>
This Bean implements Interceptor for all response
</description>
</bean>
<cxf:bus>
<cxf:inInterceptors>
<ref bean="cxfHttpRequestHandler" />
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="cxfHttpResponseHandler" />
</cxf:outInterceptors>
</cxf:bus>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.